Solidity中变量按作用域划分有三种,分别是状态变量(state variable),局部变量(local variable)和全局变量(global variable)
状态变量是数据存储在链上的变量,所有合约内函数都可以访问 ,gas消耗高。状态变量在合约内、函数外声明:
- contract Variables {
- uint public x = 1;
- uint public y;
- string public z;
- }
我们可以在函数里更改状态变量的值:
- function foo() external{
- // 可以在函数里更改状态变量的值
- x = 5;
- y = 2;
- z = "0xAA";
- }
局部变量是仅在函数执行过程中有效的变量,函数退出后,变量无效。局部变量的数据存储在内存里,不上链,gas低。局部变量在函数内声明:
- function bar() external pure returns(uint){
- uint xx = 1;
- uint yy = 3;
- uint zz = xx + yy;
- return(zz);
- }
全局变量是全局范围工作的变量,都是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): 当前链 idblock.coinbase ( address ): 挖出当前区块的矿工地址block.difficulty ( uint ): 当前区块难度block.gaslimit ( uint ): 当前区块 gas 限额block.number ( uint ): 当前区块号block.timestamp ( uint): 自 unix epoch 起始当前区块以秒计的时间戳gasleft() returns (uint256) :剩余的 gasmsg.data ( bytes ): 完整的 calldatamsg.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的别名) 被移除了。