Solidity:变量与常量

2024-05-28 20:37:37 浏览数 (2)

1. 变量

在Solidity中,存在三种主要类型的变量:局部(Local)变量、状态(State)变量和全局(Global)变量。它们的作用范围和行为各不相同。需要注意的一点是,状态变量和全局变量的使用可能会耗费更多的gas,因为它们涉及到在区块链上存储和读取数据。因此,应该尽量减少这两种类型变量的使用,特别是在需要大量计算的函数中。

1.1 局部变量(Local Variables)

局部变量是在函数内部声明的变量。它们只能在声明它们的函数中访问,当函数执行结束后,它们就会被销毁。例如:

代码语言:javascript复制
function doSomething() public {
    uint localVariable = 10;  // 这是个局部变量
}

这里,localVariable只在doSomething函数中存在和可访问。

1.2 状态变量(State Variables)

状态变量是在合约级别声明的变量。它们的生命周期与合约相同,并且在整个合约中都是可访问的。状态变量存储在区块链的存储中,这意味着它们的状态在事务之间也会持久化。例如:

代码语言:javascript复制
contract MyContract {
    uint stateVariable;  // 这是个状态变量

    function doSomething() public {
        stateVariable = 10;
    }
}

这里,stateVariableMyContract的所有函数中都可以访问。

1.3 全局变量(Global Variables)

全局变量在所有合约中都是可访问的,并且它们通常用于获取有关区块链本身或特定交易的信息。虽然它们被称为"全局"变量,但实际上它们是一组预定义的变量,不能被更改,只能用于读取。例如:

代码语言:javascript复制
function showInfo() public view returns (address, uint) {
    return (msg.sender, now);
}

这里,msg.sendernow是全局变量,分别代表当前函数调用的发送者地址和当前块的时间戳。

在Solidity中,全局变量是包含关于区块链、交易或合约本身的关键信息的一组预定义的变量。它们包括:

1.block:这个全局变量包含了当前区块的信息如下:•block.number(当前区块的编号)•block.timestamp(当前区块的时间戳)•block.difficulty(当前区块的挖矿困难度)•block.gaslimit(当前区块的gas上限)2.msg:此变量包含了当前交易的信息,如:•msg.sender(当前调用者的地址)•msg.value(在交易中发送的以太币数量,以wei为单位)•msg.data(完整的调用数据)•msg.sig(调用的函数签名)•msg.gas(在发送交易时提供的gas)3.tx:此变量在函数执行过程中包含了当前交易的信息,如:•tx.origin(执行当前调用的外部账户的地址,不是合约地址)4.now:当前区块的时间戳,相当于block.timestamp。5.abi:这是一个关于当前合约ABI编码和解码函数的全局对象,包括:•abi.encode(...)abi.encodePacked(...)abi.encodeWithSelector(...)abi.encodeWithSignature(...)abi.decode(...)6.this:此变量指向当前合约,可用以调用合约自身的函数及合约地址。7.gasleft():此函数返回当前函数还可使用的gas量。

以上就是Solidity支持的主要全局变量和函数。需要注意的是,因为这些全局变量和函数提供了关于区块链和交易的信息,所以它们只在函数执行期间有效。之后的代码执行可能会看到全新的值。

1.4 示例

代码语言:javascript复制
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

contract Variables {
    // 状态变量存储在链上
    string public hi = "hello";
    uint256 public i = 234;

    function doSomething() public view  {
        // 局部变量,定义在函数中,不在链上存储
        uint256 localVariable = 10;

        // 通过全局变量msg获取合约调用者地址
        address caller = msg.sender;

        // 通过全局变量block获取当前区块链高度
        uint bn = block.number;

    }
}

2. 常量

在Solidity中,有两种主要的方式可以声明不变的(不可修改的)值:常量Constants和Immutable。

2.1 常量Constants

constant关键字表示变量的值在编译时就被确定,且在整个合约生命周期中不会改变。它们不会占用存储空间,也不能与状态变量互动。constant通常用于定义固定的值,如数学常数、固定地址等。例如:

代码语言:javascript复制
uint constant X = 32;
string constant TEXT = "Hello, World!";

在这里,XTEXT在整个合约生命周期中都是不变的。

2.2 Immutable(不可变)

immutable是个较新的关键字。这种类型的变量在创建合约时可以被赋值一次,且此后其值在合约生命周期内不可更改。不同于constantimmutable变量的值可以在构造函数中进行计算并在运行时赋值。它们保存在合约的代码中,不占用存储空间。例如:

代码语言:javascript复制
address immutable owner;

constructor() {
    owner = msg.sender;
}

在这个例子中,owner只在构造函数中被赋值,然后在合约生命周期内保持不变。

值得注意的是,尽管immutableconstant都是用来生成不可变的变量,但它们适用于不同的场景。如果你的值在编译时已知并且永远不会改变,应使用constant。如果你的值需要在运行时(例如在构造函数中)计算或稍后确定,应使用immutable

2.3 示例

代码语言:javascript复制
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

contract Constants{
    address immutable public  owner;
    uint constant public num = 1234;

    constructor(){
         owner = msg.sender;
    }
    function setOwner(address _addr)public {
        owner = _addr;      // TypeError: Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor.
    }

    function setNum(uint _num)public {
        num = _num;         // TypeError: Cannot assign to a constant variable.
    }
}

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)[1]进行许可,使用时请注明出处。 Author: mengbin[2] blog: mengbin[3] Github: mengbin92[4] cnblogs: 恋水无意[5] 腾讯云开发者社区:孟斯特[6]

References

[1] 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0): https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh [2] mengbin: mengbin1992@outlook.com [3] mengbin: https://mengbin.top [4] mengbin92: https://mengbin92.github.io/ [5] 恋水无意: https://www.cnblogs.com/lianshuiwuyi/ [6] 孟斯特: https://cloud.tencent.com/developer/user/6649301

0 人点赞