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.gasmsg.gas 在 0.4.21 开始不推荐使用,在 0.5.0 已经移除了。


注解

在 0.7.0, now ( block.timestamp 的别名) 被移除了。