Solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)
1. 状态变量
状态变量是数据存储在链上的变量,所有合约内函数都可以访问 ,gas消耗高。状态变量在合约内、函数外声明:
contract Variables {
uint public x = 1;
uint public y;
string public z;
}
我们可以在函数里更改状态变量的值:
function foo() external{
// 可以在函数里更改状态变量的值
x = 5;
y = 2;
z = "0xAA";
}
2. 局部变量
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存储在内存里,不上链,gas低。局部变量在函数内声明:
function bar() external pure returns(uint){
uint xx = 1;
uint yy = 3;
uint zz = xx + yy;
return(zz);
}
3. 全局变量
全局变量是全局范围工作的变量,都是solidity预留关键字。他们可以在函数内不声明直接使用:
function global() external view returns(address, uint, bytes memory){
address sender = msg.sender;
uint blockNum = block.number;
bytes memory data = msg.data;
return(sender, blockNum, data);
}
补充区块和交易属性其他列表:
-
blockhash(uint blockNumber) returns (bytes32)
:指定区块的区块哈希 —— 仅可用于最新的 256 个区块且不包括当前区块,否则返回 0 。 -
block.basefee
(uint
): 当前区块的基础费用,参考: (EIP-3198 和 EIP-1559) -
block.chainid
(uint
): 当前链 id -
block.coinbase
(address
): 挖出当前区块的矿工地址 -
block.difficulty
(uint
): 当前区块难度 -
block.gaslimit
(uint
): 当前区块 gas 限额 -
block.number
(uint
): 当前区块号 -
block.timestamp
(uint
): 自 unix epoch 起始当前区块以秒计的时间戳 -
gasleft() returns (uint256)
:剩余的 gas -
msg.data
(bytes
): 完整的 calldata -
msg.sender
(address
): 消息发送者(当前调用) -
msg.sig
(bytes4
): calldata 的前 4 字节(也就是函数标识符) -
msg.value
(uint
): 随消息发送的 wei 的数量 -
tx.gasprice
(uint
): 交易的 gas 价格 -
tx.origin
(address
): 交易发起者(完全的调用链)
注解
对于每一个**外部函数**调用,包括
msg.sender
和msg.value
在内所有msg
成员的值都会变化。这里包括对库函数的调用。
注解
当合约在链下被评估,而不是在一个区块所包含的交易的背景下被评估时,你不应该假定 block.* 和 tx.* 是指任何特定区块或交易。这些值是由执行合约的EVM实现提供的,可以是任意的。
注解
不要依赖
block.timestamp
和blockhash
产生随机数,除非你明确知道自己做的用意。时间戳和区块哈希在一定程度上都可能受到挖矿矿工影响。例如,挖矿社区中的恶意矿工可以用某个给定的哈希来运行赌场合约的 payout 函数,而如果他们没收到钱,还可以用一个不同的哈希重新尝试。
当前区块的时间戳必须严格大于最后一个区块的时间戳,但这里能确保也需要它是在权威链上的两个连续区块。
注解
基于可扩展因素,区块哈希不是对所有区块都有效。你仅仅可以访问最近 256 个区块的哈希,其余的哈希均为零。
注解
blockhash
函数之前是使用block.blockhash
,block.blockhash
在 0.4.22 开始不推荐使用,在 0.5.0 已经移除了。
注解
gasleft
函数之前是使用msg.gas
,msg.gas
在 0.4.21 开始不推荐使用,在 0.5.0 已经移除了。
注解
在 0.7.0,
now
(block.timestamp
的别名) 被移除了。