[마스터링 이더리움] 스마트 컨트랙트 보안 - 패턴12 블록 timestamp 조작

in #busy5 years ago

블록 timestamp 조작

  • 채굴자는 블록 timestamp를 살짝 조작할 수 있다.
  • timestmap가 잘못 사용되면 심각한 문제를 초래할 수 있다.

취약점

  • 채굴자는 block.timestamp, 이것의 alias(참조)인 now를 조작할 수 있다. 일정 정도의 동기부여가 되면 말이다.
  • Roulette 컨트랙트
1 contract Roulette {
2   uint public pastBlockTime; // forces one bet per block
3
4   constructor() public payable {} // initially fund contract
5
6   // fallback function used to make a bet
7   function () public payable {
8     require(msg.value == 10 ether); // must send 10 ether to play
9     require(now != pastBlockTime); // only 1 transaction per block
10    pastBlockTime = now;
11    if(now % 15 == 0) { // winner
12      msg.sender.transfer(this.balance);
13    }
14  }
15 }
  • 간단한 복권 게임 컨트랙트이다. 블록당 1개의 트랙잰션은 10 이더를 베팅할 수 있다.
  • 이 게임의 가정은 block.timestamp의 마지막 두 자리가 동일한 확률로 나온다는 것이다. (균일 확률)
  • 채굴자는 block.timestamp의 15 모듈러값이 0이 되도록 timestamp를 선택할 수 있다. (모듈러 연산은 예를 들면, 시간을 나타낼 때, 13시의 경우 모듈러 12로 하면 1시가 된다)
  • 또한 이것은 블록당 한 사람만 베팅할 수 있도록 했기 때문에, 프런트 러닝 문제에 취약하다. (솔루션 탈취!)

예방기법

  • 블록 timestamp로 임의수를 발생하게 하면 안된다. 게임의 결정적 요소가 되게 하면 안된다.
  • 시간을 사용하고자 한다면 block.number와 평균 블록 시간을 사용하여 시간을 추정하는 것이 좋다.
  • 이때, 특정 블록을 선택하여 계산하는 것이 좋다. 왜냐하면 채굴자는 블록 번호를 조작할 수 없기 때문이다.

Coin Marketplace

STEEM 0.17
TRX 0.15
JST 0.028
BTC 61940.19
ETH 2433.78
USDT 1.00
SBD 2.50