抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

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
  • 即:image-20230223131719894

3.解题

  • 3.1 先从题目中获取关卡的地址:

  • image-20230223131941603

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

  • image-20230223132159058

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

  • image-20230223132529971

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

  • image-20230223132706272

  • 3.5 查看当前合约的owner

  • image-20230223132850570

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

  • image-20230223133025174

  • 3.7 回到题目提交实例

  • 3.8 返回结果,通过!!!:

image-20230223131056772

评论



政策 · 统计 | 本站使用 Volantis 主题设计