{"content":{"title":"区块链开发必备（1）——合约升级方案","body":"## **基础**\r\n基于 Openzeppelin V3\r\n文档 https://docs.openzeppelin.com/contracts/3.x/upgradeable\r\n\r\n## **做法**\r\n定义合约的时候要继承 ERC721Upgradeable\r\n\r\n\r\n```js\r\ncontract MyCollectible is ERC721Upgradeable\r\n```\r\n\r\n\r\n安装 upgrade 插件，文档 https://docs.openzeppelin.com/upgrades-plugins/1.x/\r\n\r\n\r\n```js\r\n$ npm install --save-dev @openzeppelin/hardhat-upgrades @nomiclabs/hardhat-ethers ethers\r\n```\r\n\r\n\r\n\r\n升级合约的时候使用 hardhat 的 upgrades 插件\r\n\r\n```js\r\n// scripts/deploy-my-collectible.js\r\n  const { ethers, upgrades } = require(\"hardhat\");\r\n\r\n  async function main() {\r\n    const MyCollectible = await ethers.getContractFactory(\"MyCollectible\");\r\n\r\n    const mc = await upgrades.deployProxy(MyCollectible);\r\n\r\n    await mc.deployed();\r\n    console.log(\"MyCollectible deployed to:\", mc.address);\r\n  }\r\n\r\n  main();\r\n```\r\n\r\n更详细的流程可以这篇教程 https://forum.openzeppelin.com/t/openzeppelin-upgrades-step-by-step-tutorial-for-hardhat/3580\r\n\r\n## **原理**\r\n当创建一个新的可升级合约实例时，OpenZeppelin升级插件实际上部署了三个合约。\r\n● 你写的合约，也就是所谓的包含逻辑的合约实现。\r\n● 一个ProxyAdmin，作为代理的管理员。\r\n● 一个指向实现合约的代理，也就是你实际交互的合约。\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/7cZzSFVH636cddd953c39.png)\r\n\r\n\r\n升级则包括以下步骤。\r\n● 部署新的实现合约\r\n● 向代理发送一个事务，将其实现地址更新为新的实现地址。\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/1HEoijyz636cdde5a654b.png)\r\n\r\n注意：合约的逻辑可以被升级，但是 store 还是在 proxy 里，是无法升级的\r\n\r\n## **FAQ**\r\n为什么可升级的合约不能有构造函数？\r\nproxy admin 的作用是什么？"},"author":{"user":"https://learnblockchain.cn/people/12541","address":null},"history":"QmcLoHce9LK45rgPabcYHmHvLAAsF2K9aDZFaMt8fD1RsS","timestamp":1668127631,"version":1}