Solidity transient storage

한 트랜잭션 내에서만 유지되고, 트랜잭션이 끝나면 자동으로 초기화되는 임시 저장소이다. EIP-1153에서 소개되었다. TSTORETLOAD opcode 로 접근할 수 있으며, EVM Cancun 버전부터 지원한다. Solidity 0.8.24 부터 지원된다. 재진입 락으로 주로 이용된다.

어셈블리를 이용하여 Transient 스토리지의 슬롯 번호를 지정하여 사용할 수 있다. 슬롯은 영구 스토리지와는 별도로 관리된다.

contract TransientAssembly {
    // slot 번호
    bytes32 constant SLOT = bytes32(uint256(1));
 
    function tstore(uint256 value) external {
        assembly {
            tstore(SLOT, value)
        }
    }
 
    function tload() external view returns (uint256 value) {
        assembly {
            value := tload(SLOT)
        }
    }
}

하이레벨에서 접근하려면 다음과 같이 사용할 수 있다.

contract OverwriteStorage {
    address transient _lock;
 
    function guarded() external {
        require(_lock == address(0), "locked");
        _lock = msg.sender;
        // ... protected logic ...
        delete _lock;
    }
}

Transient storage clearing helper collision bug

Solidity 0.8.28 - 0.8.33 컴파일러에서 Transient 스토리지를 삭제할 때 스토리지가 잘못 삭제되는 버그가 존재한다. Solidity 0.8.34에서 이를 수정했다.

예를 들어 다음과 같은 코드가 있다. 영구 스토리지 슬롯 0번에 owner 변수가, transient 스토리지 슬롯 0번에 _lock이 저장되어 있다. guarded 함수에서 delete _lock; 으로 transient 스토리지를 클리어한다.

contract OverwriteStorage {
    // ---- persistent storage ----
    address public owner;
    mapping(uint256 => address) public delegates;
 
    // ---- transient storage ----
    address transient _lock;
 
    constructor() { owner = msg.sender; }
 
    function clearDelegate(uint256 id) external {
        delete delegates[id];
    }
 
    function guarded() external {
        require(_lock == address(0), "locked");
        _lock = msg.sender;
        // ... protected logic ...
@>      delete _lock;
    }
}

이때 transient 가 아니라 영구 스토리지인 owner 변수가 초기화 된다. transient 스토리지는 초기화되지 않았으므로 동일 트랜잭션에서 guarded 재호출 시 트랜잭션이 revert 된다.

OverwriteStorage target = new OverwriteStorage();
assert(target.owner() == address(this));  // owner is deployer
 
target.guarded();
assert(target.owner() == address(0));     // owner overwritten with zero

tags: blockchain, smart contract, solidity, solidity storage