[Ethernaut CTF] FallOut

0xDave·2022년 10월 3일
0

Ethereum

목록 보기
23/112

소스코드


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

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

해결 과제


Claim ownership of the contract below to complete this level.

  Things that might help

    Solidity Remix IDE

ownership 가져오기


해결 과정


컨트랙트의 owner를 보니 0x0000000000000000000000000000000000000000다. 해당 주소의 소유자는 없으며 이러한 주소는 보통 소각용 주소라고 알고 있다. 그렇다면 어떻게 ownership을 가져올 수 있을까?

constructor는 배포될 때 맨 처음에 실행되는 함수다. 소스코드에는 constructor 키워드가 있는 함수가 없으니 Fal1out() 함수가 가장 처음에 실행될 것이고 이는 constructor역할을 한다고 볼 수 있다. 시험삼아 Fal1out() 함수를 호출해봤는데 아무 이상 없이 호출됐다.(???)

찾아보니 constructor 키워드가 솔리디티 버전 0.4.22 이전에는 없었다고 한다. 따라서 그 때는 가장 처음 작성한 function을 constructor 역할로 작성한 것 같다. 그런데 소스코드에는 컨트랙트 이름(Fallout)과 맨 처음 작성한 함수의 이름(Fal1out)이 묘하게 다르다. l1로 잘못쓴 것. 이렇게 이름이 달라지게 되면 constructor 역할을 수행하지 못한다고한다. 따라서 public으로 선언된 첫 번째 함수는 누구나 부를 수 있게 되고, ownership 또한 넘어간다. 솔리디티 버전 0.4.22 이후에는 constructor 키워드가 생겨 이러한 문제를 방지한 것으로 보인다. 따라서 이번에도 인스턴스 제출 후 끝!

profile
Just BUIDL :)

0개의 댓글