我有一个智能合同部署在ethereum网络上,我可能必须根据未来的需求更改来更改它,因为它们是不可变的,那么我可以在多大程度上对我的智能合同进行更改?
假设我想在我的智能契约中添加一个或多个新变量(S),这可能吗?
代理方法允许我在智能契约中添加另一个变量吗?使用代理方法可以进行多少更改?
发布于 2021-07-29 23:10:29
对于可升级的智能契约和各种方法,有相当多的警告。
在代理方法中,您指的是代理智能契约与逻辑智能契约的交互。
契约状态存储在代理契约中,逻辑通过逻辑契约执行。在执行升级时,它指的是创建一个与代理契约相关联的不同的逻辑契约。
通过EVM的操作码delegatecall,代理契约与逻辑契约之间的关系在可升级性方面成为可能。这将在调用者状态的上下文中执行被调用者的代码。
逻辑契约控制代理的状态,逻辑契约的状态是无意义的。因此,代理不仅向逻辑契约转发事务,而且还表示对的状态。状态在代理中,逻辑在代理所指向的特定实现中。
代理是一个简单的契约,它只是将所有调用委托给一个实现契约。委托调用类似于常规调用,但所有代码都是在调用方的上下文中执行的,而不是在被调用方的上下文中执行的。正因为如此,实现契约代码中的传输实际上将传递代理的余额,任何对契约存储的读或写都将从代理自己的存储中读取或写入。
另一个重要的考虑因素是可能发生的存储冲突,在初始部署时使用非结构化存储,然后在新版本中附加存储层次结构。
对于可升级的智能契约,您不能使用构造函数,因为在稳固性中,位于构造函数或全局变量声明中的代码并不是已部署的契约运行时字节码的一部分。在部署契约实例时,构造函数代码只执行一次。因此,逻辑契约构造函数中的代码永远不会在代理状态的上下文中执行。换句话来说,代理完全忽略了构造函数的存在。就好像他们不是代理的人一样。
解决这个问题的方法是实现初始化函数,而不是构造函数。而且,如果您使用的是OpenZeppelin,那么就必须使用openzeppelin-contracts-upgradeable,因为所有的子合同都必须有这个结构。
此警告进一步适用于相当于构造函数的字段声明的初始值,即
contract MyContract {
uint256 public hasInitialValue = 42; // equivalent to setting in the constructor
}这应该设置为
contract MyContract is Initializable {
uint256 public hasInitialValue;
function initialize() public initializer {
hasInitialValue = 42; // set initial value in initializer
}
}最后,还考虑了函数冲突(代理和逻辑中相同的函数名)。这可以使用transparent proxy pattern来解决。
然而,不同名称的函数之间也不可避免地发生冲突。这是因为在字节码级别上,每个契约ABI都由一个4字节的标识符标识。只有4个字节,两个不同名称的函数可能具有相同的标识符。Solidity编译器在同一契约中跟踪这一点-但是,在代理契约的情况下,->逻辑契约,编译器无法跟踪它,因为它的两个单独的智能契约。
因此,这里的总体总结是,可升级的智能契约实例(代理)通过将所有调用委托给逻辑智能契约来工作。低级别调用delegatecall使之成为可能。不能使用构造函数,因为它们不是已部署的智能契约的运行时字节码的一部分,因此逻辑契约构造函数中的代码永远不会在代理状态的上下文中执行。与构造函数相关的后者对于字段声明的初始值也是如此。
https://ethereum.stackexchange.com/questions/104153
复制相似问题