블록체인 학습
0 XP

block 전역 변수와 시간

Solidity 에는 호출이나 블록의 정보를 담은 전역 변수(global variables)가 있습니다. 이 중 block 과 msg 는 컨트랙트 로직에서 특히 자주 쓰입니다. 선언 없이 어디서나 바로 읽을 수 있고, 값은 EVM 이 실행 시점에 채워 줍니다.

block 전역 변수

block 에는 현재 트랜잭션이 담긴 블록의 정보가 들어 있습니다.

표현식의미
block.timestamp현재 블록의 Unix 타임스탬프(초 단위)
block.number현재 블록 번호
block.chainid현재 체인의 ID (예: 이더리움 메인넷 = 1)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract BlockInfo {
    function currentTime() public view returns (uint256) {
        return block.timestamp;
    }
 
    function currentBlock() public view returns (uint256) {
        return block.number;
    }
 
    function chainId() public view returns (uint256) {
        return block.chainid;
    }
}

block.timestamp 는 초 단위로 시간을 비교할 때, block.number 는 몇 블록이 지났는지로 기간을 잴 때 씁니다. block.chainid 는 멀티체인 환경에서 다른 체인의 서명이 재사용(replay)되지 않는지 확인할 때 쓰입니다.

msg 전역 변수 복습

표현식의미
msg.sender현재 함수를 호출한 주소
msg.value함수 호출과 함께 보낸 Ether 의 양 (wei 단위)

msg.sender 는 접근 제어(예: onlyOwner)에, msg.value 는 결제 로직에 핵심적으로 쓰입니다.

시간 기반 로직

block.timestamp 를 이용하면 "마감 시간이 지났는가?", "잠금 기간이 끝났는가?" 같은 시간 조건을 만들 수 있습니다. 보통 배포 시점에 기준 시각을 저장해두고, 나중에 현재 시각과 비교합니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract TimeLock {
    uint256 public unlockTime;
 
    constructor(uint256 lockSeconds) {
        unlockTime = block.timestamp + lockSeconds; // 지금부터 lockSeconds 초 뒤
    }
 
    function isUnlocked() public view returns (bool) {
        return block.timestamp >= unlockTime;
    }
}

지분증명(PoS) 전환 이후 이더리움의 블록은 12초 슬롯마다 만들어지고, block.timestamp 는 그 슬롯 시각에 거의 고정됩니다. 즉 제안자가 초 단위로 값을 주무르지는 못하는 대신, 다음 블록의 타임스탬프가 미리 예측 가능 합니다. 따라서 block.timestamp 를 난수원으로 쓰면 공격자가 결과를 미리 계산할 수 있으므로, 도박·추첨처럼 예측 불가능성이 필요한 로직에는 절대 쓰면 안 됩니다. 반면 며칠·몇 주 단위의 잠금처럼 거친 시간 비교에는 안전하게 사용할 수 있습니다.

Solidity 는 1 days, 1 weeks 같은 시간 단위 리터럴을 제공합니다. block.timestamp + 7 days 처럼 쓰면 초 단위 계산 실수를 줄일 수 있습니다.

아래 에디터에서 배포 시각을 기록하는 컨트랙트를 직접 컴파일해보세요. Run 을 누르면 됩니다.

Code Editor
에디터를 불러오는 중...
실행 결과

Run 버튼을 눌러 코드를 실행하세요.