如需获取本内容的最新版本,请参见 Cyfrin.io 上的瞬态存储(代码示例)
transient torage瞬态存储(或者叫临时storage,交易storage)中的数据在交易完成后会被清除。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
// 确保EVM版本和虚拟机设置为Cancun
// storage - 数据存储在区块链上
// memory - 函数调用后数据被清除
// Transient storage - 交易完成后数据被清除
interface ITest {
function val() external view returns (uint256);
function test() external;
}
// 测试TestStorage和TestTransientStorage的合约
// 展示普通storage与临时存储之间的差异
contract Callback {
uint256 public val;
fallback() external {
val = ITest(msg.sender).val();
}
function test(address target) external {
ITest(target).test();
}
}
contract TestStorage {
uint256 public val;
function test() public {
val = 123;
bytes memory b = "";
msg.sender.call(b);
}
}
contract TestTransientStorage {
bytes32 constant SLOT = 0;
function test() public {
assembly {
tstore(SLOT, 321)
}
bytes memory b = "";
msg.sender.call(b);
}
function val() public view returns (uint256 v) {
assembly {
v := tload(SLOT)
}
}
}
// 测试重入保护的合约
contract MaliciousCallback {
uint256 public count = 0;
//尝试多次重新进入目标合约
fallback() external {
ITest(msg.sender).test();
}
// 测试发起重入攻击
function attack(address _target) external {
// First call to test()
ITest(_target).test();
}
}
contract ReentrancyGuard {
bool private locked;
modifier lock() {
require(!locked);
locked = true;
_;
locked = false;
}
// 27587 gas
function test() public lock {
// 忽略调用错误
bytes memory b = "";
msg.sender.call(b);
}
}
contract ReentrancyGuardTransient {
bytes32 constant SLOT = 0;
modifier lock() {
assembly {
if tload(SLOT) { revert(0, 0) }
tstore(SLOT, 1)
}
_;
assembly {
tstore(SLOT, 0)
}
}
// 4909 gas
function test() external lock {
// 忽略调用错误
bytes memory b = "";
msg.sender.call(b);
}
}
Remix Lite 尝试一下
END