ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

部署OpenZeppelin可升级合约

2022-01-29 17:35:55  阅读:292  来源: 互联网

标签:Box box value rinkeby 升级 truffle OpenZeppelin 合约


使用OpenZeppelin升级插件部署的合约具备可升级的特性:可以升级以修改其代码,同时保留其地址,状态和余额。 可以迭代地向项目中添加新功能,或修复在线上版本中可能发现的任何错误。

配置开发环境

创建一个新的npm项目

mkdir mycontract && cd mycontract
npm init -y

安装并初始化Truffle

npm i --save-dev truffle
npx truffle init

安装Truffle升级插件

npm i --save-dev @openzeppelin/truffle-upgrades

创建可升级合约

注意,可升级合约使用initialize函数而不是构造函数来初始化状态。

Box.sol

// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
 
contract Box {
    uint256 private value;
 
    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);
 
    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }
 
    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

将合约部署到公共网络

我们将使用Truffle迁移来部署Box合约。Truffle升级插件提供了一个 deployProxy功能来部署可升级合约。它将部署我们实现的合约,ProxyAdmin会作为项目代理和代理管理员,并调用初始化函数。

在migrations目录中创建以下2_deploy_box.js脚本。

在本文中,我们还没有initialize函数,因此将使用store 函数来初始化状态。

2_deploy_box.js

// migrations/2_deploy_box.js
const Box = artifacts.require('Box');
 
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
 
module.exports = async function (deployer) {
  await deployProxy(Box, [42], { deployer, initializer: 'store' });
};

使用Rinkeby网络运行truffle migration进行部署。 我们可以看到3 个合约:Box.sol、ProxyAdmin 和 代理合约AdminUpgradeabilityProxy。

truffle migrate --network rinkeby

...
2_deploy_box.js
===============

   Deploying 'Box'
   ---------------
   > transaction hash:    0x3263d01ce2e3eb4ba51abf882abbdd9252364b51eb972f82958719d60a8b9ebe
   > Blocks: 0            Seconds: 5
   > contract address:    0xd568071213Ea31B01AA2247BC9eC7285087cf882
...
   Deploying 'ProxyAdmin'
   ----------------------
   > transaction hash:    0xf39e8cb97c332b8bbdf0c66b13f26a9a3dc97b207d2caec73ba6df8d5bb6b211
   > Blocks: 1            Seconds: 17
   > contract address:    0x2A210B6d5EffC0A3BB47dD3791a4C26B8E31f161
...
   Deploying 'AdminUpgradeabilityProxy'
   ------------------------------------
   > transaction hash:    0x439711597b694f03b1065582ab44ac0bea5e22b0c6e3c460ae7b4536f004c355
   > Blocks: 1            Seconds: 17
   > contract address:    0xF325bB49f91445F97241Ec5C286f90215a7E3BC6
...

发布验证合约

truffle run verify Box --network rinkeby

我们可以使用Truffle控制台(truffle console)与我们的合约进行交互。

注意: Box.deployed() 是我们的代理合约的地址。

truffle console --network rinkeby

truffle(rinkeby)> box = await Box.deployed()
truffle(rinkeby)> box.address
'0xc2ea7DE43F194bB397761a30a05CEDcF28835F24'
truffle(rinkeby)> (await box.retrieve()).toString()
'42'

当前代理的管理员(可以执行升级)是ProxyAdmin合约。 只有ProxyAdmin的所有者可以升级代理。 警告:ProxyAdmin 所有权转移时请确保转到我们控制的地址上。

3_transfer_ownership.js

// migrations/3_transfer_ownership.js
const { admin } = require('@openzeppelin/truffle-upgrades');
 
module.exports = async function (deployer, network) {
  // 使用你的 钱包 地址
  const admin = '0x1c14600daeca8852BA559CC8EdB1C383B8825906';
 
  // Don't change ProxyAdmin ownership for our test network
  if (network !== 'test') {
    // The owner of the ProxyAdmin can upgrade our contracts
    await admin.transferProxyAdminOwnership(admin);
  }
};

在Rinkeby网络上运行迁移

truffle migrate --network rinkeby

...
3_transfer_ownership.js
=======================

   > Saving migration to chain.
   -------------------------------------
...

实现一个新的升级版本

一段时间后,我们决定要向合约添加功能。 在本文中,我们将添加一个increment函数。

注意:我们无法更改之前合约实现的存储布局,有关技术限制的更多详细信息,请参阅升级。

使用以下Solidity代码在你的contracts目录中创建新的实现BoxV2.sol 。

BoxV2.sol

// contracts/BoxV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
 
contract BoxV2 {
    uint256 private value;
 
    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);
 
    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }
    
    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
    
    // Increments the stored value by 1
    function increment() public {
        value = value + 1;
        emit ValueChanged(value);
    }
}

部署新的升级版本

一旦测试了新的实现,就可以准备升级。 这将验证并部署新合约。 注意:我们仅是准备升级。。

4_prepare_upgrade_boxv2.js

// migrations/4_prepare_upgrade_boxv2.js
const Box = artifacts.require('Box');
const BoxV2 = artifacts.require('BoxV2');
 
const { prepareUpgrade } = require('@openzeppelin/truffle-upgrades');
 
module.exports = async function (deployer) {
  const box = await Box.deployed();
  await prepareUpgrade(box.address, BoxV2, { deployer });
};

在Rinkeby网络上运行迁移,以部署新的合约实现

truffle migrate --network rinkeby

...
4_prepare_upgrade_boxv2.js
==========================

   Deploying 'BoxV2'
   -----------------
   > transaction hash:    0x078c4c4454bb15e3791bc80396975e6e8fc8efb76c6f54c321cdaa01f5b960a7
   > Blocks: 1            Seconds: 17
   > contract address:    0xEc784bE1CC7F5deA6976f61f578b328E856FB72c
...

 进入truffle控制台

truffle console --network rinkeby

truffle(rinkeby)> box = await Box.deployed()
truffle(rinkeby)> boxV2 = await BoxV2.deployed()
truffle(rinkeby)> box.address
'0xF325bB49f91445F97241Ec5C286f90215a7E3BC6'
truffle(rinkeby)> boxV2.address
'0xEc784bE1CC7F5deA6976f61f578b328E856FB72c'

升级合约

执行ProxyAdmin合约的upgrade方法

proxy:TransparentUpgradeableProxy合约的地址

implementation:BoxV2合约的地址

然后需要在MetaMask(或你正使用的钱包)中签署交易。

现在,我们可以与升级后的合约进行交互。 我们需要使用代理地址与BoxV2进行交互。 然后,我们可以调用新的“增量”功能,观察到整个升级过程中都保持了状态。

进入truffle控制台

truffle console --network rinkeby

truffle(rinkeby)> box = await Box.deployed()
truffle(rinkeby)> boxV2 = await BoxV2.at(box.address)
truffle(rinkeby)> (await boxV2.retrieve()).toString()
'42'
truffle(rinkeby)> await boxV2.increment()
{ tx:
...
truffle(rinkeby)> (await boxV2.retrieve()).toString()
'43'

标签:Box,box,value,rinkeby,升级,truffle,OpenZeppelin,合约
来源: https://blog.csdn.net/watson2017/article/details/122745389

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有