Alex Park
Hexlant
Published in
4 min readFeb 18, 2018

--

SafeMath는 왜 써야하는가?

일반적으로 스마트컨트랙트에서 숫자 연산을 할 때 공통적으로 발생하는 문제는 오버플로우, 언더플로우의 위험입니다. 이 포스팅에서는 실제 오버플로우, 언더플로우가 발생하는 예제와 OpenZeppelin의 SafeMath 라이브러리를 사용하여 오버, 언더플로우를 예방하는 방법에 대해 알아보겠습니다.

add 실행 시 45번 라인 assert(c ≥ a); 조건을 통해 오버플로우가 발생하였을 경우 에러를 발생시켜 더이상 진행되지 않게 됩니다.

sub 실행시 36번 라인 assert(b ≤ a); 조건을 통해 언더플로우를 예방합니다. 해당 조건에 맞지 않을 경우 에러를 발생시켜 더이상 진행되지 않게 됩니다.

아래 예제는 오버플로우를 보여주기 위해 uint8 type(0 ~255)으로 예제를 만들었습니다. 기존 SafeMath 라이브러리는 uint256 type으로 작성 되어 있기 때문에 예제를 실행 하기 위해서 uint8 type 으로 라이브러리를 새로 만들었습니다.

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

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

using SafeMath for uint8;

function add(uint8 num) public pure returns (uint8) {
uint8 result = 255;
return result + num;
}

function sub(uint8 num) public pure returns (uint8) {
uint8 result = 0;
return result - num;
}

function safeAdd(uint8 num) public pure returns (uint8) {
uint8 result = 255;
return result.add(num);
}

function safeSub(uint8 num) public pure returns (uint8) {
uint8 result = 0;
return result.sub(num);
}

// function expectedCompileError() public pure returns (uint8) {
// uint8 max = 256; // compile time error
// uint8 min = 0 - 1; // compile time error
// return 0;
// }
}
  • 테스트
  1. add(1)을 실행시 결과값은 0을 리턴 (오버플로우)
  2. sub(1)을 실행시 결과값은 255을 리턴 (언더플로우)
  3. safeAdd(1)을 실행시 에러 발생 (오버플로우)
  4. safeSub(1)을 실행시 에러 발생 (언더플로우)

끝으로 OpenZeppelin 은 스마트컨트랙트를 보다 안전하게 만들 수 있게 도와주는 프레임워크입니다. SafeMath 뿐만 아니라 다양한 라이브러리와 컨트랙트 예제들이 주기적으로 업데이트 되고 있으니 아래 github 에서 다른 예제들도 참고하면 좋을것 같습니다.

--

--