Ethernaut题库闯关连载第9篇, 使用transfer 的注意点。
今天这篇是Ethernaut 题库闯关连载的第9篇,难度等级:有点难。
Ethernaut 题库闯关我已经整理为一个专栏了, 欢迎大家订阅专栏。
King合约代表了一个非常简单的游戏:谁发送的以太币数量大于当前的奖金,谁就成为新的国王。在这种情况下,被推翻的国王会得到新的奖金,在这个过程中赚取一点以太币! 就像庞氏骗局那样一个有趣的游戏。
你的目标是要破坏这个合约。使自己称为国王之后,其他人再也无法称为国王,你就完成了这个挑战。
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract King {
address payable king;
uint public prize;
address payable public owner;
constructor() public payable {
owner = msg.sender;
king = msg.sender;
prize = msg.value;
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
function _king() public view returns (address payable) {
return king;
}
}
在查看解题思路之前,可以自己先想一想,停一下,这样才有更大的提高。
本次挑战的关键是了解 transfer
函数的局限。
状态变量:
address payable king
是当前国王的地址。当新的国王即位时,老国王将收到发送到receive
函数的msg.value
。uint public prize;
如果你想成为新的国王,你需要向合约发送的最低值ETH,新的国王即位会更新。address payable public owner
合约的所有者。函数:
constructor() public payable {
owner = msg.sender;
king = msg.sender;
prize = msg.value;
}
构造函数只是设置了合约的变量: owner
和当前的 king
是 msg.sender
(合约的部署者)以及prize
,prize
是想成为新国王的最低发送金额。
function _king() public view returns (address payable)
solidity这个函数只是返回当前的国王
receive() external payable
这是我们感兴趣的主要函数。我们已经知道,receive
函数是一个特殊的函数,允许合约直接从外部合约或EOA接收ethers,回顾一下receive的代码:
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
我们看到的第一件事是 require(msg.value >= prize || msg.sender == owner)
。这个检查允许合约的 owner
始终拥有合约的王权,重设所有的值。
从安全的角度来看,这是一个巨大的问...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!