Fallback题解
1. 题目要求
① 获得这个合约的所有权 ② 把它的合约余额减到0
提示:
- 如何通过与ABI互动发送ether
- 如何在ABI之外发送ether
- 转换 wei/ether 单位 (参见
help()
命令)
- Fallback 方法
合约代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
contract Fallback {
mapping(address => uint) public contributions; address public owner;
constructor() { owner = msg.sender; contributions[msg.sender] = 1000 * (1 ether); }
modifier onlyOwner { require( msg.sender == owner, "caller is not the owner" ); _; }
function contribute() public payable { require(msg.value < 0.001 ether); contributions[msg.sender] += msg.value; if(contributions[msg.sender] > contributions[owner]) { owner = msg.sender; } }
function getContribution() public view returns (uint) { return contributions[msg.sender]; }
function withdraw() public onlyOwner { payable(owner).transfer(address(this).balance); }
receive() external payable { require(msg.value > 0 && contributions[msg.sender] > 0); owner = msg.sender; } }
|
2. 分析
- 2.1 该题的题眼在于,通过owner = msg.sender语句把合约的所有权设置为合约调用者,观察分析合约可知,在contribute()方法和 receive() 方法中拥有该语句,但如果执行contribute() 的话需要调用 0.001 * 1000000 + 1次 显然这样的作法是不可取的,故 只能采用receive()方法来实现
- 2.2 receive()成功调用的条件是,调用者的贡献值大于0.001ether 还用支付 > 0的费用,我们只能通过调用contribute()函数改变合约调用者的贡献值,改好之后就可以调用到合约的receive()函数,就可以成为合约的拥有者
- 2.3 最后调用withdraw() 函数将合约的钱全部转给owner
- 即:

3.解题
3.1 先从题目中获取关卡的地址:

3.2 到remix中,将网络和账户切换为自己的钱包账户,

3.3 给自己的钱包账户加入贡献值 contributions

3.4 调用receive() 函数,实现获取 合约所有权操作

3.5 查看当前合约的owner

3.6 最后调用withdraw() 函数,将合约的余额全部转出

3.7 回到题目提交实例
3.8 返回结果,通过!!!:
