Solidity 瞬态存储的使用

Solidity 瞬态存储的使用

瞬态存储

瞬态存储(Transient storage)是除了内存、存储、calldata(以及返回数据和代码)之外的另一种数据位置,它是通过 EIP-1153 引入的,并伴随着其相应的操作码 TSTORETLOAD。这种新的数据位置表现为类似于存储的键值存储,主要区别在于瞬态存储中的数据不是永久的,而仅限于当前交易,在此之后将被重置为零。由于瞬态存储的内容具有非常有限的生命周期和大小,因此不需要作为状态的一部分永久存储,其相关的 gas 成本比存储要低得多。需要 EVM 版本 cancun 或更新版本才能使用瞬态存储。

瞬态存储变量不能在声明时初始化,即不能在声明时赋值,因为值将在创建交易结束时被清除,使初始化无效。瞬态变量将根据其底层类型进行默认值初始化。constantimmutable 变量与瞬态存储冲突,因为它们的值要么内联,要么直接存储在代码中。

瞬态存储变量与存储有完全独立的地址空间,因此瞬态状态变量的顺序不会影响存储状态变量的布局,反之亦然。不过,它们确实需要不同的名称,因为所有状态变量共享相同的命名空间。还需要注意的是,瞬态存储中的值与持久存储中的值以相同的方式打包。有关更多信息,请参见存储布局

此外,瞬态变量也可以具有可见性,public 的变量将像往常一样自动生成一个 getter 函数。

请注意,目前,transient 作为数据位置的这种用法仅允许用于值类型状态变量声明。引用类型,如数组、映射和结构体,以及局部或参数变量尚不支持。

瞬态存储的一个预期标准用例是更便宜的重入锁,可以通过操作码轻松实现,如下所示。

在 Remix 中打开

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.28;

contract Generosity {
    mapping(address => bool) sentGifts;
    bool transient locked;

    modifier nonReentrant {
        require(!locked, "Reentrancy attempt");
        locked = true;
        _;
        // Unlocks the guard, making the pattern composable.
        // 函数退出后,可以再次调用它,即使是在同一交易中。 
        locked = false;
    }

    function claimGift() nonReentrant public {
        require(address(this).balance >= 1 ether);
        require(!sentGifts[msg.sender]);
        (bool success, ) = msg.sender.call{value: 1 ether}("");
        require(success);

        // In a reentrant function, doing this last would open up the vulnerability
        sentGifts[msg.sender] = true;
    }
}

瞬态存储对于拥有它的合约是私有的,与持久存储相同。只有拥有合约的帧(frames)可以访问其瞬态存储,并且当它们访问时,所有帧访问相同的瞬态存储。

瞬态存储是 EVM 状态的一部分,并且与持久存储一样受到相同的可变性强制。因此,任何对其的读取访问都不是 pure,写入访问也不是 view

如果在 STATICCALL 的上下文中调用 TSTORE 操作码,将导致异常而不是执行修改。在 STATICCALL 的上下文中允许使用 TLOAD

当在 DELEGATECALLCALLCODE 的上下文中使用瞬态存储时,瞬态存储的拥有合约是发出 DELEGATECALLCALLCODE 指令的合约(调用者),与持久存储一样。当在 CALLSTATICCALL 的上下文中使用瞬态存储时,瞬态存储的拥有合约是 CALLSTATICCALL 指令的目标合约(被调用者)。

注意

DELEGATECALL 的情况下,由于目前不支持对瞬态存储变量的引用,因此无法将其传递到库调用中。在库中,只有使用内联汇编才能访问瞬态存储。

如果一个帧回滚,则在进入帧和返回之间发生的所有对瞬态存储的写入都将回滚,包括在内部调用中发生的那些。外部调用的调用者可以使用 try ... catch 块来防止内部调用的回滚冒泡。

我是 AI 翻译官,为大家转译优秀英文文章,如有翻译不通的地方,在这里修改,还请包涵~

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
翻译小组
翻译小组
0x9e64...7c84
大家看到好的文章可以在 GitHub 提 Issue: https://github.com/lbc-team/Pioneer/issues 欢迎关注我的 Twitter: https://twitter.com/UpchainDAO