ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SmartContract 개발에 유의해야할 점 (2/2)
    IT 지식 2019. 5. 10. 12:04

    [이전글] SmartContract 개발에 유의해야할 점 (1/2)

     

    SmartContract 개발에 유의해야할 점 (1/2)

    오늘은 그 동안 블록체인 SmartContract를 개발하며 느낀 점들을 정리해보려고 한다. 블록체인은 잘 알지 못하지만 개발면에서 우수한 개발자분들이 미리 작성해주신 Contract Code를 볼 때 그리고, 블록체인 서비..

    ryublock.tistory.com

    2. 고려해야할 항목

    2-1. GAS

     SmartContract 개발시 가장 신경을 써야하는 부분은 GAS비용이다. 얼마나 최적화가 되있느냐에 따라 GAS 소모량을 줄일 수 있고, 이는 유저와 서비스 제공자에게도 큰 이점으로 작용한다.

    SafeMath library Multiplication

    위의 상황은 SafeMath 라는 library 이다. 왼쪽 기존 SafeMath에서는 a == 0 일때라는 조건 검사를 넣지 않았다.

    그렇기 때문에 정답이 0이 될 것을 알면서도 0 * ?을 수행했다.

    반면 오른쪽 변경된 SafeMath에서는  a == 0 일때 곱셈을 수행하지 않고, 0을 즉시 반환했다.

     

    그렇게 execution cost를 살펴 보면 변경 된 SafeMath가 Gas비용을 절약한 것을 볼 수 있다.

    a가 0일때, 25Gas b가 0일 때 1Gas 절약이지만 해당 SmartContract에서 곱셈 연산이 얼마나 발생되느냐에 따라 더 큰 비용감소를 이끌어낼 수 있다.

     

    b == 0 을 검사하지 않은 이유는 a,b 두 가지 항목을 비교하게 될 경우 0 검사를 하지 않는 왼쪽에 비해 이익이 발생하지 않기 때문이다. https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522

     


    상황에 따라 수정하기

    필자는 Smart Contract를 작성 할 때마다, library 혹은 기타 코드들을 상황에 맞추어 최대한 변형하여 사용하려고 노력한다.

    작성한 Contract의 곱셈 연산들의 빈도와 거기서 0이 연산될 확률을 잘 생각해보아야한다.

    a 혹은 b의 인자가 0이 될 확률이 높다면 a == 0 뿐 만아니라  b == 0 또한 검사하는 것이 가스비 절약에 도움이 될 것이다.

    반대로 0이 연산될 확률이 없을 경우, if(a == 0) 을 제외 시키면 가스비가 절약될 것이다.

     

    이렇게 상황에 따라 Contract 코드는 달라질 수 있어야하며, 이것은 Transaction이 쌓여갈 때마다 더 큰 Gas비용을 절약할 수 있게 된다.


    Example

    이번에 진행한 파일럿 프로젝트에서 유저에게 일 10회 보상을 주는 기능이 있었다. 보상 횟수를 초기화하는 방법에는 여러가지가 있겠지만 필자가 생각한 방법은 User가 마지막으로 기록한 시간 UserData.lastTimeStamp를 Day로 변환하고, 현재 TimeStamp를 Day로 변환하여 비교하는 방법이였다. Day가 같다면 Month를 비교하였다.

     

    여기서 한 가지 문제가 발생될 수 있다.

    2018년 5월 10일에 글을 작성하고, 2019년 5월 10일에 복귀하여 글을 작성하는 유저는 보상 횟수가 초기화가 안되는 문제이다.

    하지만 위와 같은 상황이 발생될 확률에 비해 조건검사로 소모되는 Gas비용이 훨신 크다고 판단하기 때문에 비교하지 않았다.

     

    [year을 검사하는 조건문 추가 가정]

    Gas Limit 약 300Gas

    Gas Price 약 10 Gwei

    Transaction Fee 0.000003 ETH (이더 20만원 기준 0.6원)

     

    서비스에서 하루에 10,000건의 Transaction이 발생된다고 했을 때 약 6,000원이라는 금액이 나온다.

    그렇기 때문에 우리는 여러 상황과 Gas 비용에 대하여 우위를 결정해야한다.

    function checkResetRewardCount() private {
        // UTC+09:00
        uint8 lastDay = getDay(userStore[msg.sender].lastTimeStamp + 32400);
        uint8 curDay = getDay(now + 32400);
        
        if(lastDay != curDay) {
            userStore[msg.sender].rewardCount = 0;
        } else {
            uint8 lastMonth = getMonth(userStore[msg.sender].lastTimeStamp + 32400);
            uint8 curMonth = getMonth(now + 32400);
            
            if(lastMonth != curMonth) {
                userStore[msg.sender].rewardCount = 0;
            }
        }
    }

     

    2-2. 예외처리 (코드검증 & Test의 중요성)

     SMT 해킹 상태는 Overflow를 이용하여 토큰을 전송 시킨 사건이였다.

     

     

    if(balances[_from] < _feeSmt + _value) revert();

    _feeSmt + _value에서 Overflow 검사만 있었다면 위와 같은 사태는 일어나지 않았을 것이다.

    아이콘에 심각한 취약점이 있다는 주장이 제기됐다
    아이콘 "이미 알고 있는 내용, 실제로는 보안상 문제 없다"

    [아이콘] 관리자 빼고 다 가능하게 하라!

    그 외에도 조건문을 반대로 작성하여 관리자만 호출해야할 함수를 관리자를 제외하고 호출가능하게 만드는 사례도 있었다.

    모두 굉장히 우스운 사례이지만 배포 이후 수정하기가 쉽지 않기 때문에 Contract 작성자는 예외처리에 많은 신경을 써야한다.

     

    파일럿 프로젝트 Review

     

    댓글

Developer RyuK