Могу ли я отключить прямые транзакции на адрес смарт-контракта?

Я хочу использовать переменную rewardsAmount для расчета вознаграждения:

uint вознагражденияСумма = 0;

// Только здесь я могу вывести награды

функция removeRewards() onlyВладелец внешний
{
    требуется (сумма вознаграждения! = 0);
    владелец.transfer (сумма вознаграждения);
    сумма вознаграждения = 0;
}

// Если в контракте нет средств пользователей, то я могу его уничтожить

только функция kill() Владелец внешний
{
    требуют(адрес(этот).баланс - сумма вознаграждения == 0);
    самоуничтожение (владелец);
}

функция someFunction() публичная
{
    // какой-то код
    сумма вознаграждения += 100;
}

Если кто-то отправит на адрес контракта немного эфира, я никогда не смогу убить контракт, верно? Итак, как я могу предотвратить отправку эфира на мой контракт?

Ответы (2)

Нет, вы не можете предотвратить отправку эфира на ваш контракт.

Помните, что эфир может быть принудительно отправлен на счет

Остерегайтесь кодировать инвариант, который строго проверяет баланс контракта.

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

Злоумышленник может сделать это, создав контракт, финансируя его с помощью 1 wei и вызвав selfdestruct(victimAddress). Код жертвы не вызывается, поэтому предотвратить это невозможно. Это также верно для вознаграждения за блок, которое отправляется на адрес майнера, который может быть любым произвольным адресом.

Кроме того, поскольку адреса контрактов могут быть предварительно вычислены, эфир может быть отправлен на адрес до того, как контракт будет развернут.

См. SWC-132

Источник: https://consensys.github.io/smart-contract-best-practices/recommendations/#remember-that-ether-can-be-forcely-sent-to-an-account

Вы не можете надежно отклонить средства, переведенные на контрактный адрес. Будьте осторожны, чтобы не сделать вектор атаки (отключить ваш selfdestruct), потому что кто-то selfdestruct(yourContract)покажет вам ошибку. Ой!

Более неясный способ — это охота за пасхальными яйцами, но не слишком надуманная. Учитывая адрес развертывателя и одноразовый номер, адрес развернутого контракта предсказуем , поэтому можно иметь положительный баланс до развертывания контракта . Это полезно для эзотерических шаблонов, озорства и возможного саботажа, если ваш контракт, опять же, использует address(this).balanceважную логику. Имейте в виду, что это может быть не то, что вы ожидаете.

Я понимаю, что это надуманный пример. Настоящая опасность здесь заключается в использовании address(this).balanceлогики. В интересах всех, кто еще сталкивался, я бы отговаривал selfdestructвообще. Самоуничтожение — это ошибка .

Надеюсь, поможет.

Большое спасибо! Итак, мне нужно использовать «function pause () onlyOwner { pause = true }»? И я не понимаю эту часть, «потому что кто-то самоуничтожит (ваш контракт), чтобы показать вам ошибку». Где я могу прочитать больше об этом?
Да. Обычно лучше заморозить все функции вместо самоуничтожения. Вам также нужен модификатор, onlyIfRunningи он должен require(!pause, "the contract is stopped.").
В вашем контракте использовалось самоуничтожение для отправки денег владельцу. Кто-то другой может самоуничтожить свой контракт, чтобы вложить деньги в ваш контракт, и это нельзя отменить - исходный вопрос (название), поэтому нет, вы не можете. Не на 100% надежный, так что...
Теперь я понял)) Еще раз спасибо, я многому научился.