可能是世界上第一张木制银行卡

# 现可免费申请,无工本费、快递费、年费,中国可送达。

> 传送门:TreeCard

写在前面

我放弃了

关于

地址

第一条是Rinkeby测试链的题,因为水龙头日常罢工,所以余额不好整,推荐使用第二个Ropsten测试链的。

WriteUp

Level 0 [Hello Ethernaut]

第一次接触以太坊,一脸懵逼,只能照着文本引导一步一步来了。

先在浏览器上装了个MetaMask,建了个钱包,然后换成Ropsten测试链。

然后在水龙头Ropsten Ethereum (rETH) Faucet上领取5个测试ETH。

之后回到平台,点击Get new instance,进行合约交互,等控制台显示Instance address字样就是创建好实例了。

然后照着文本提示输入await contract.info()命令,返回You will find what you need in info1().
输入await contract.info1()命令,返回Try info2(), but with "hello" as a parameter.
输入await contract.info2("hello")命令,返回The property infoNum holds the number of the next info method to call.
输入await contract.infoNum()命令,返回42
输入await contract.info42()命令,返回theMethodName is the name of the next method.
输入await contract.theMethodName()命令,返回The method name is method7123949.
输入await contract.method7123949()命令,返回If you know the password, submit it to authenticate().
输入await contract.password()命令,返回ethernaut0
输入await contract.authenticate("ethernaut0")命令,进行登录,等待交易确认。

最后点击Submit instance即可提交实例进行评测,若操作无误即可拿到合约源码。

image.png

pragma solidity ^0.5.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) public {
    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;
  }
}

Chrome内核版本在62以上的务必在每个命令之前加上await,不然返回会很奇怪,而且password似乎不会被初始化导致无法获取返回。

Level 1 [Fallback]

题目给了通关要求:

  1. 拿到合约的拥有权
  2. 转出所有余额

先看看给的合约代码。

pragma solidity ^0.5.0;

import 'openzeppelin-solidity/contracts/math/SafeMath.sol';

contract Fallback {

  using SafeMath for uint256;
  mapping(address => uint) public contributions;
  address payable public owner;

  constructor() public {
    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 {
    owner.transfer(address(this).balance);
  }

  function() payable external {
    require(msg.value > 0 && contributions[msg.sender] > 0);
    owner = msg.sender;
  }
}

发现我根本看不懂solidity语言,等我有空了能看个大概了再回来做。


To be Continued


什么都会,但又什么都不会。