【问题标题】:Solidity: Why use Initialize function instead of constructor?Solidity:为什么使用 Initialize 函数而不是构造函数?
【发布时间】:2022-12-18 15:19:54
【问题描述】:

我正在做审计智能合约,有人喜欢使用这样的初始化函数:

 bool private isInit=false;
 string private hello;
 
 function init(string _hello) public onlyOwner {
   hello = _hello;
   isInit = true;
 } 

 function doSomething() public {
   require(isInit, "Wait for initialize");
   ...doSomething
 }

你能解释一下为什么不使用构造函数吗?

【问题讨论】:

    标签: architecture state ethereum solidity smartcontracts


    【解决方案1】:

    您作为示例编写的初始化是错误的,因为它可能被所有者多次调用,初始化器(以及构造函数)的目的是在使用合同之前作为第一个函数被调用,并且永远不会被调用第二次回来

    然而,当一个合约使用一个代理人发表

    为什么?

    在以太坊中,主要有三种类型的合约调用:定期通话,静态调用, 和代表电话.

    签约时一个做一个称呼合同通过调用foo(),函数执行依赖合约的存储,并且 msg.sender 设置为 contract一个.

    这是因为契约一个调用了函数foo(),这样msg.sender就是合约一个的地址和msg.value 将是与该函数调用一起发送的 ETH。在该函数调用期间对状态所做的更改只会影响合约.

    但是,当使用代表电话, 函数foo() 将在合同中被调用 但在合同的范围内 一个.这意味着合同的逻辑将被使用,但函数foo()所做的任何状态更改都会影响合约的存储一个.而且,msg.sender 将指向首先拨打电话的 EOA。

    我们该如何处理构造函数逻辑?合约的构造函数在合约部署期间自动调用。

    但是当代理人正在发挥作用,因为构造函数只会更改实施合约的存储(乙合约),而不是存储代理人合同(合约甲),这是最重要的。

    因此,需要一个额外的步骤。我们需要更改常规函数中的构造函数。此函数通常称为初始化或初始化,一旦两个合约都已发布,将在代理合约上调用此函数,以保存代理合约上的所有状态更改(合约A)而不是实施(合约乙)

    【讨论】:

    • 很好的解释和图表!
    【解决方案2】:

    openzeppelin docs explains:

    构造函数警告

    在 Solidity 中,构造函数中的代码或全局变量的一部分 变量声明不是已部署合约运行时的一部分 字节码。这段代码只执行一次,当合约实例 已部署。因此,逻辑中的代码 合约的构造函数永远不会在 代理的状态。换句话说,代理完全无视 构造函数的存在。就好像他们不在那里一样 代理。

    不过问题很容易解决。逻辑合约应该移动 构造函数中的代码到常规的“初始化程序”函数,以及 每当代理链接到此逻辑时调用此函数 合同。需要特别注意这个初始化器 函数,以便它只能被调用一次,这是其中之一 一般编程中构造函数的属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 2012-06-28
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      相关资源
      最近更新 更多