솔리디티 SafeMath 이해하기

Poo·2022년 1월 22일
0

오버플로와 언더플로는 프로그램이 무한루프를 걸리게 하거나 고장나게 할 수 있다. 그러나 이더리움은 이러한 문제를 가스비를 이용해 자동으로 판단을 하도록 설계를 해두었다. 또한 프로그래밍 상에서 가스비로 해당 함수의 실행이 실패가 되는 경우를 자동으로 예외처리하게 해주는 여러 함수들이 제공된다.

SafeMath

솔리디티에서 uint256 자료형은 0부터 2^256-1 만큼의 값을 제공
범위 이하의 값을 할당하거나, 범위 이상의 값을 할당하는 경우 언더플로, 오버플로 문제가 발생

안전하게 연산을 가능 하도록 SafeMath라는 함수를 만들어보자

Interface 부분에 작성해준다.

library SafeMath {
  	function mul(uint256 a, uint256 b) internal pure returns (uint256) {
		uint256 c = a * b;
		assert(a == 0 || c / a == b);
		return c;
  	}

  	function div(uint256 a, uint256 b) internal pure returns (uint256) {
	    uint256 c = a / b;
		return c;
  	}

  	function sub(uint256 a, uint256 b) internal pure returns (uint256) {
		assert(b <= a);
		return a - b;
  	}

  	function add(uint256 a, uint256 b) internal pure returns (uint256) {
		uint256 c = a + b;
		assert(c >= a);
		return c;
	}
}

메인컨트렉트부분

contract SimpleToken is ERC20Interface {
    using SafeMath for uint256;
    //uint256으로 선언된 함수에 대해서 SafeMath Library를 이용해서 해당 함수를 사용을 할 수 있다.
....
     function transferFrom(address sender, address recipient, uint256 amount) external virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        emit Transfer(msg.sender, sender, recipient, amount);
        uint256 currentAllowance = _allowances[sender][msg.sender];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        
       //아래//
        _approve(sender, msg.sender, currentAllowance, currentAllowance.sub(amount));
        
         // 다음의 코드에서 currentAllowance.sub(amount)이 SafeMath 라이브러리 함수를 사용한 예시
         
        return true;
    }

    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");
        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        //아래//
        _balances[sender] = senderBalance.sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
    }

uint256으로 선언했던 currentAllowance와 senderBalance에 sub 함수를 사용 가능한 모습을 볼 수 있다
또한 Mapping으로 선언했던 _balances도 uint256으로 받아오는 값에서 add 함수를 사용 가능하다

오버플로와 언더플로가 일어나게 된다면 currentAllowance, senderBalance를 검사하는 require에서 문제가 발생한다.

profile
죽을 때 까지 공부하다 죽을 인생, 로봇공학자에서 블록체인 개발자가 되기 까지

0개의 댓글