常量和不可變狀態(tài)變量

2022-05-16 10:46 更新

狀態(tài)變量可以聲明為constant或immutable。在這兩種情況下,變量在合約構(gòu)建后都不能修改。對(duì)于constant變量,值必須在編譯時(shí)固定,而對(duì)于immutable,它仍然可以在構(gòu)造時(shí)賦值。

也可以constant在文件級(jí)別定義變量。

編譯器不會(huì)為這些變量保留存儲(chǔ)槽,每次出現(xiàn)都會(huì)被相應(yīng)的值替換。

與常規(guī)狀態(tài)變量相比,常量和不可變變量的 gas 成本要低得多。對(duì)于常量變量,分配給它的表達(dá)式被復(fù)制到所有訪問它的地方,并且每次都重新計(jì)算。這允許局部?jī)?yōu)化。不可變變量在構(gòu)造時(shí)被評(píng)估一次,它們的值被復(fù)制到代碼中訪問它們的所有位置。對(duì)于這些值,保留 32 個(gè)字節(jié),即使它們可以容納更少的字節(jié)。因此,常量值有時(shí)可能比不可變值便宜。

目前并非所有常量和不可變類型都已實(shí)現(xiàn)。唯一支持的類型是 字符串(僅用于常量)和值類型

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.4;

uint constant X = 32**22 + 8;

contract C {
    string constant TEXT = "abc";
    bytes32 constant MY_HASH = keccak256("abc");
    uint immutable decimals;
    uint immutable maxBalance;
    address immutable owner = msg.sender;

    constructor(uint decimals_, address ref) {
        decimals = decimals_;
        // Assignments to immutables can even access the environment.
        maxBalance = ref.balance;
    }

    function isBalanceTooHigh(address other) public view returns (bool) {
        return other.balance > maxBalance;
    }
}

持續(xù)的

對(duì)于constant變量,該值在編譯時(shí)必須是一個(gè)常量,并且必須在聲明變量的地方賦值。任何訪問存儲(chǔ)、區(qū)塊鏈數(shù)據(jù)(例如block.timestamp,address(this).balance或 block.number)或執(zhí)行數(shù)據(jù)(msg.valuegasleft())或調(diào)用外部合約的表達(dá)式都是不允許的。允許可能對(duì)內(nèi)存分配產(chǎn)生副作用的表達(dá)式,但不允許對(duì)其他內(nèi)存對(duì)象產(chǎn)生副作用的表達(dá)式。允許使用內(nèi)置函數(shù) keccak256、sha256ripemd160、和 (盡管除了 之外ecrecover,它們確實(shí)調(diào)用了外部合約)。addmodmulmodkeccak256

允許對(duì)內(nèi)存分配器產(chǎn)生副作用的原因是應(yīng)該可以構(gòu)造復(fù)雜的對(duì)象,例如查找表。此功能尚未完全可用。

不可變

聲明為的變量immutable比聲明為的變量的限制要少一些constant:不可變變量可以在合約的構(gòu)造函數(shù)中或在它們的聲明點(diǎn)被分配一個(gè)任意值。它們只能分配一次,從那時(shí)起,即使在施工期間也可以讀取。

編譯器生成的合約創(chuàng)建代碼將在返回之前修改合約的運(yùn)行時(shí)代碼,將所有對(duì)不可變對(duì)象的引用替換為分配給它們的值。如果您將編譯器生成的運(yùn)行時(shí)代碼與實(shí)際存儲(chǔ)在區(qū)塊鏈中的運(yùn)行時(shí)代碼進(jìn)行比較,這一點(diǎn)很重要。

筆記

在聲明時(shí)分配的不可變對(duì)象僅在合約的構(gòu)造函數(shù)執(zhí)行后才被視為已初始化。這意味著您不能使用依賴于另一個(gè)不可變對(duì)象的值內(nèi)聯(lián)初始化不可變對(duì)象。但是,您可以在合約的構(gòu)造函數(shù)中執(zhí)行此操作。

這是為了防止對(duì)狀態(tài)變量初始化和構(gòu)造函數(shù)執(zhí)行順序的不同解釋,特別是在繼承方面。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)