[Solidity] block.timestamp manipultation

임형석·2023년 10월 31일
0

Solidity


Block.timestamp

솔리디티는 가장 최근 생성 블록의 생성 시간을 불러오는 전역변수가 있다.

block.timestamp 변수를 사용하면 UNIX 시간으로 값을 받을 수 있다.

그리고 현재 이더리움의 블록은 매 10~15초 사이에 생성이 된다.

이렇게 변화하는 값을 이용한다면 다음과 같이 간단한 게임을 만들 수 있다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract game {
    constructor() payable {
        require(msg.value == 2 ether, "Require 2 ethers to activate.");
        payable(this).transfer(2 ether);
    }

    receive() external payable {}

    function start() public payable {
        require(msg.value == 1 ether, "require 1 ether.");

        (bool transfer, ) = address(this).call{value : msg.value}("");
        require(transfer,"Failed to send ether.");

        if(block.timestamp % 7 == 1){
            payable(msg.sender).transfer(address(this).balance - 2 ether);
        }
    }

    function guessTime(uint _unixTime) public payable {
        require(msg.value == 1 ether, "require 1 ether.");

        (bool transfer, ) = address(this).call{value : msg.value}("");
        require(transfer,"Failed to send ether.");

        if(block.timestamp == _now){
            payable(msg.sender).transfer(address(this).balance - 2 ether);
        }
    }
}

game 컨트랙트의 start, guessTime 함수를 사용해 게임에 참여할 수 있다.

게임에 참여하는 start 함수를 실행하는 트랜잭션을 보낼 때의 값이,

block.timestamp % 7 == 1 이라는 조건에 맞아야 컨트랙트에 있는 이더를 받을 수 있다.

guessTime 함수는 인자를 unix 시간으로 받으며, 현재 시간을 정확히 맞춘다면 이더를 받을 수 있다.


블록 생성과 Manipulation

핵심은, 이더리움 블록의 타임스탬프는 정확하지 않다.

첫 번째 이유는, 채굴자가 네트워크 시간의 특정 범위 내에 있으면 타임스탬프를 어느 정도 조작할 수 있다. 따라서 타임스탬프는 블록이 채굴된 시점을 정확히 측정한 것이 아닌 채굴된 시간의 근사치이다.

두 번째 이유로는, 블록의 채굴 과정을 생각해볼때 네트워크 지연 및 다른 요인들로 인해 정보가 이더리움 네트워크를 통해 전송되는 데 걸리는 시간의 변동에 타임스탬프의 값이 영향을 받을 수 있다.


15-second Rule

The 15-second Rule

"The Yellow Paper"는 블록이 시간적으로 얼마나 떠있을 수 있는지에 대한 제약을 명시하지는 않지만, 각 타임스탬프는 부모 블록의 타임스탬프보다 커야 한다고 명시합니다. 인기 있는 이더리움 프로토콜인 Geth와 Parity는 모두 미래 15초 이상의 타임스탬프를 가진 블록을 거부합니다. 따라서 타임스탬프 사용을 평가할 때 좋은 지침은 다음과 같습니다 :

만약 시간에 따라 변하는 이벤트의 시간 척도가 15초 내외로 변할 수 있고 무결성을 유지할 수 있다면, 블록 타임스탬프 (block.timestamp)를 사용하는 것이 안전합니다.

라고 설명하고 있다.

인기 있는 이더리움 프로토콜인 Geth와 Parity는 새로 생성하는 블록이 이전 블록 타임스탬프 +15초 이상의 타임스탬프 값을 갖고 있다면, 블록 자체를 거부한다고 한다.

따라서 "타임스탬프는 항상 근사치이며 정확한 값이 아니다" 라는 것, 그리고 블록의 생성은 매 10~15초 이며 ~15초 정도의 변동성을 감안하는 15초 룰을 염두하며 개발하면 될 것이다.


0개의 댓글