[마스터링 이더리움] 스마트 컨트랙트 보안 - 패턴15 부동소숫점 정밀도

in #kr5 years ago

부동소숫점 정밀도

  • 솔리티디(0.4.24 기준)는 고정 소숫점과 부동소숫점을 지원하지 않는다.
  • 즉, 부동소숫점의 정밀도를 int타입 변수로 조절해야 한다.

취약점

  • FunWithNumbers 컨트랙트
1 contract FunWithNumbers {
2   uint constant public tokensPerEth = 10;
3   uint constant public weiPerEth = 1e18;
4   mapping(address => uint) public balances;
5
6   function buyTokens() public payable {
7     // convert wei to eth, then multiply by token rate
8     uint tokens = msg.value/weiPerEth*tokensPerEth;
9     balances[msg.sender] += tokens;
10  }
11
12  function sellTokens(uint tokens) public {
13    require(balances[msg.sender] >= tokens);
14    uint eth = tokens/tokensPerEth;
15    balances[msg.sender] -= tokens;
16    msg.sender.transfer(eth*weiPerEth);
17  }
18 }
  • 위 코드의 8행에서 정수 나눗셈에서 문제가 발생한다.
  • 정수 타입으로 1/10을 하면 0이 된다. 이것은 변수의 타입이 정수이기 때문에 발생한다.

예방기법

  • 비율을 사용할 때는 분자에 큰 수가 올 수 있는지 확인해야 한다.
  • 약간의 소숫점 정밀도 손실은 있겠지만, 가능하면 분자를 크게 한 후 나눗셈을 하라.
  • 더욱 좋은 방법은 매우 높은 정밀도로 변수값을 변환해서 계산한 후, 요구되는 값으로 변환하는 것이다.

Coin Marketplace

STEEM 0.30
TRX 0.11
JST 0.033
BTC 64271.38
ETH 3157.43
USDT 1.00
SBD 4.25