Разбор кода EasyInvest5 v2

Разбор кода EasyInvest5 v2

По всем вопросам @alexkirsanoff


Адрес контракта:
0x87c73aD7EA75743cadfB02C1AD0d926A46869cDF

Код на etherscan: https://etherscan.io/address/0x87c73ad7ea75743cadfb02c1ad0d926a46869cdf#code


Что было добавлено нового в контракт:

  • Защита от быстрого роста. Ежедневно баланс контракта может расти не более чем на 10% от размера его прошлых инвестиций.
  • Расчет суммы для выплаты дивидендов теперь основывается не на блоках, а на метках времени UNIX
  • Теперь, если на балансе контракта не хватает суммы для выплаты инвестору дивидендов, контракт отправит ему имеющийся остаток


Обзор кода:

Первой строкой мы указываем версию компилятора для solidity, в данном случае это версия 0.4.25. Прошлый контракт имел версию 0.4.24

Версия компилятора solidity (1-ая строчка)


Далее идет описание функционала смартконтракта EasyInvest5 в виде комментариев, которые никак не влияют на код.

Комментарии с 3 по 22 строчки


Следующей строчкой объявляем контракт с названием EasyInvest5. В фигурных скобках заключено тело смартконтракта.

Далее идет объявление публичных маппингов контракта (ассоциативных массивов), где ключ - это адрес пользователя.

В invested хранятся значения вкладов, измеряемых в wei

1 wei = 0.000000000000000001 ETH

В dates хранится время последней инвестиции вкладчика в формате UNIX времени

Объявление публичных маппингов: invested и dates


Следом идёт объявление трех публичных положительных целочисленных значений контракта:

totalInvested - хранит в себе сумму всех депозитов инвесторов с момента создания контракта

canInvest - общая доступная сумма инвестиций. Имеет по умолчанию значение в 50ETH. Это значение является стартовым, оно определяет максимальный размер суммы, которую могут инвестировать вкладчики в первый день жизни смарт контракта.

refreshTime - метка времени UNIX, указывающая на дату, когда необходимо обновить доступную сумму инвестиций (переменную canInvest). По умолчанию refreshTime принимает значение, равное текущей отметки времени плюс 1 день.

Объявление публичных переменных: totalInvested, canInvest, refreshTime

На 38 строчке мы объявляем fallback функцию, которая будет вызываться, когда кто-то просто переводит ethereum на счет смартконтракта (даже если ethereum равен нулю). Далее идет тело данной функции


Если инвестор уже делал депозит в контракт, то выполняется блок кода с 41 по 51 строчку (условие проверки на 40 строчке).

На 43 строчке идет подсчет суммы для выплаты инвестору:

Сумма для выплаты =
[инвестированный баланс пользователя] * 5 *
([текущая отметка времени] - [отметка времени
прошлой инвестиции]) / 100 / 24 часа

Поскольку в solidity нет дробных чисел, то в подсчете формулы сначала ведётся умножение всех необходимых комнонентов, затем только деление.

Отметки времени UNIX исчисляются в секундах, 24 hours является всего лишь псевдонимом значения 86400. 86400 - это количество секунд в одном дне.

На 46 строчке идёт условие проверки:

Если доступная сумма на вывод превышает баланс контракта (address(this).balance), то тогда (далее 47 строчка) сумма для вывода становится равной имеющемуся остатку, то есть всему оставшемуся балансу контракта

На 51 строчке отправляется выплата через метод transfer инвестору, которую ее запросил:

msg.sender - это адрес инвестора

На 52 фигурной скобкой закрывается тело условия

На 55 строчке в маппинге dates по ключу адреса инвестора обновляем временную метку UNIX до текущей

Обновление временной метки инвестора


На 58 строчке происходит проверка. Если UNIX время, хранящиеся в refreshTime (см. выше) наступило, то тогда выполняются строчки 60 и 61.

На 60 строчке происходит обновление общей доступной суммы инвестиций за день:

Доступная суммая для инвестиций = неизрасходованная оставшаяся часть инвестиций с прошлых дней + 10% от суммы всех депозитов инвесторов

На 61 строчке обновляется отметка времени refreshTime на 1 день вперед


На 64 строчке идёт очередное условие проверки: если инвестор отправил сумму (msg.value), которая больше нуля ETH, то выполняется блок кода с 66 по 71 строчку:

На 66 строчке проиходит проверка на возможность инвестировать данный депозит инвестором. Если этот депозит инвестора превышает значение переменной canInvest (доступная сумма для инвестиций), то контракт выбрасывает ошибку (исключение), после чего происходит откат (revert) всех изменений за текущую транзакцию.

Если же депозит инвестора меньше или равен доступной суммы для инвестиций, то выполняются последующие строки кода.


На 68 строчке к маппингу invested по ключу адреса инвестора прибавляем новую инвестированную сумму (msg.value) к текущей (по умолчанию текущая сумма равна нулю.

Затем на 70 строчке уменьшаем доступную сумму инвестиций (canInvest) на текущий депозит инвестора, а на 71 строчке к переменной totalInvested, которая хранит в себе сумму всех депозитов инвесторов, прибавляем текущий депозит

На 72 строчке закрывается тело условия, на 73 строчке тело fallback функции, а на 74 строчке тело контракта EasyInvest5


Заключение

Уязвимостей и багов в смартконтракте не обнаружено

Report Page