{"_id":"@cardstack/upgrade-manager","_rev":"10-1a4df57929e0d98ce46f1c739504a7aa","name":"@cardstack/upgrade-manager","dist-tags":{"beta":"1.0.0-beta","latest":"1.0.1"},"versions":{"1.0.0-0":{"name":"@cardstack/upgrade-manager","version":"1.0.0-0","keywords":["ethereum","smart-contracts","hardhat","hardhat-plugin"],"author":{"name":"Cardstack"},"license":"MIT","_id":"@cardstack/upgrade-manager@1.0.0-0","maintainers":[{"name":"alex-cs","email":"alex.speller@cardstack.com"},{"name":"pcjun97","email":"pcjun97@gmail.com"},{"name":"jurgen","email":"matic@jurglic.si"},{"name":"burcunoyan","email":"burcu.noyan@cardstack.com"},{"name":"ef4","email":"edward@eaf4.com"},{"name":"habdelra","email":"hassan.abdelrahman@gmail.com"},{"name":"lukemelia","email":"luke@lukemelia.com"},{"name":"aierie","email":"michael.khor@cardstack.com"}],"dist":{"shasum":"3eb2d73b6284ea353c0dc026e7369ed04923839b","tarball":"https://registry.npmjs.org/@cardstack/upgrade-manager/-/upgrade-manager-1.0.0-0.tgz","fileCount":309,"integrity":"sha512-8dqdZ6y7Lms40Z7adjT6fB9zw+efPxdueyV7hFe40nbwfVbEKqYCf0qXpkDXwlI0yFrZidT1w+Y7K8/bQpkTcA==","signatures":[{"sig":"MEUCIHpiEmucF7dOUGKKifDQeaUDN9SWppNBK0DGZBqOHixJAiEA3vAMi5MQzpT/jIBcG7pdQjPUY4BmgtwrK23+doQP+hA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1039820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjWawFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDyBAAhhVzYiVXpq5KyxGJO5tKnzlZHrATmZccEvy/ZJ1ZGFhOl5XD\r\nKkA+fcDACKy/use2QZrlkBY7YlQff2+wYvGK0IfEiPk1LEqqNVJI+iswFQMH\r\nzW/D/+VQm4xyQkdbQkXopTV+zWDaS6fjxNtXNhRfx9CFC2TJUAHxpbnHy3pL\r\nWZ/VJA5lccKpLQdrXZ/ZBHUxWoZczf8L/Ao78FAI/+BhecL0N20RQamUCzOS\r\noj97Mr5WZacHQYkCl8AW9viQaO/M61zrOrwj6Cw0knHWOvb1/ZugW15L/nng\r\n3jTtjTyvK/fNmFxgfpwXHwrkXlgqRYs0BPC0gqaBAleGHsB/XNTsGW8zjinm\r\n7Wms/at6npEtorRdi9D4TxiV2bhDaf1KD/CF6uFklmbXdgmpHcTQQRqCS91V\r\npH19qU94RQAPkJ3ANxT4chlblgfp+HiRwu4ADw/b7LCpQBPiGnxNoC3MN8uo\r\nO3nOCqV1Vleytle67tsU6hA+HZi6sCvnakPqfC/WdrifSvVss7p7Yi4ZO72r\r\nU7egE6CMrVfEF3HnFao/ex1GTdIsstcz3RaV2/MuF9Y75Vwb9KzOnmR5poKk\r\naN2RDfzEe/fY7HjX8vVkS9l5cL6lTUqjc6c56MUmbO2VVewSTyxsYxaPq9cX\r\n3Ma+Hy/6wd2ux6//MG66Kp6+PCuKkGyPpTw=\r\n=8ZVM\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/src/index.js","types":"dist/src/index.d.ts","scripts":{"lint":"yarn lint:js && yarn lint:sol && yarn lint:contract-size","test":"yarn test:sol && yarn test:plugin && yarn lint","build":"yarn compile && node_modules/.bin/tsc && cp *.sol.json ./dist/","clean":"./node_modules/.bin/hardhat clean","watch":"tsc -w","compile":" ./node_modules/.bin/hardhat compile && ./node_modules/.bin/hardhat run ./src/copy-compilation-result.ts","lint:js":"./node_modules/.bin/eslint --max-warnings 0 .","coverage":"env SILENCE_COMPILER_WARNINGS=true ./node_modules/.bin/hardhat coverage","lint:sol":"./node_modules/.bin/solhint ./contracts/\\*\\*/\\*.sol -w 0","test:sol":"./node_modules/.bin/hardhat test --typecheck","recompile":"yarn clean && yarn compile","test:plugin":"yarn build && mocha $INSPECT_FLAG --exit --recursive 'plugin-tests/**/*.test.ts'","prepublishOnly":"yarn clean && yarn build","lint:contract-size":"{ ./node_modules/.bin/hardhat size-contracts | tee /dev/fd/3 | grep -q 'exceed the size limit for mainnet deployment' && exit 1; } 3>&1 || echo 'All contracts within size limit'","test:plugin:inspect":"env INSPECT_FLAG='--inspect-brk' yarn test:plugin"},"_npmUser":{"name":"alex-cs","email":"alex.speller@cardstack.com"},"repository":{"url":"https://github.com/cardstack/upgrade-manager.git","type":"git"},"description":"Cardstack Smart Contract Upgrade Manager","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2022 Cardstack\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","dependencies":{"colors":"^1.4.0","lodash":"^4.17.21","enquirer":"^2.3.6","fs-extra":"^10.1.0","cli-table3":"^0.6.3","cpr-promise":"^0.2.6","trezor-cli-wallet-provider":"^1.0.7","@openzeppelin/hardhat-upgrades":"^1.21.0","@openzeppelin/contracts-upgradeable":"^4.8.0-rc.1","@nomicfoundation/hardhat-network-helpers":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.2.0","rmrf":"^2.0.4","mocha":"^7.1.2","eslint":"^8.24.0","ethers":"^5.7.2","hardhat":"^2.12.0","solhint":"^3.3.7","ts-node":"^8.1.0","prettier":"^2.7.1","typechain":"^8.1.0","typescript":"^4.0.3","@types/chai":"^4.1.7","@types/node":"^8.10.38","@types/mocha":"^5.2.6","test-console":"^2.0.0","@types/lodash":"^4.14.186","@types/fs-extra":"^5.0.4","chai-as-promised":"^7.1.1","solidity-coverage":"^0.8.1","@typechain/hardhat":"^6.1.2","@types/test-console":"^2.0.0","@typechain/ethers-v5":"^10.1.0","eslint-plugin-import":"^2.26.0","hardhat-gas-reporter":"^1.0.8","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","hardhat-contract-sizer":"^2.6.1","@ethersproject/providers":"^5.4.7","prettier-plugin-solidity":"^1.0.0-beta.24","@nomiclabs/hardhat-ethers":"^2.0.0","@typescript-eslint/parser":"^5.38.1","@nomiclabs/hardhat-etherscan":"^3.0.0","@nomicfoundation/hardhat-toolbox":"^2.0.0","@typescript-eslint/eslint-plugin":"^5.38.1","@nomicfoundation/hardhat-chai-matchers":"^1.0.0"},"peerDependencies":{"hardhat":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-manager_1.0.0-0_1666821125547_0.45904805835211526","host":"s3://npm-registry-packages"}},"1.0.0-beta":{"name":"@cardstack/upgrade-manager","version":"1.0.0-beta","keywords":["ethereum","smart-contracts","hardhat","hardhat-plugin"],"author":{"name":"Cardstack"},"license":"MIT","_id":"@cardstack/upgrade-manager@1.0.0-beta","maintainers":[{"name":"alex-cs","email":"alex.speller@cardstack.com"},{"name":"pcjun97","email":"pcjun97@gmail.com"},{"name":"jurgen","email":"matic@jurglic.si"},{"name":"burcunoyan","email":"burcu.noyan@cardstack.com"},{"name":"ef4","email":"edward@eaf4.com"},{"name":"habdelra","email":"hassan.abdelrahman@gmail.com"},{"name":"lukemelia","email":"luke@lukemelia.com"},{"name":"aierie","email":"michael.khor@cardstack.com"}],"dist":{"shasum":"5c4360d0321b4413dec9d491b2f4acb39db01cba","tarball":"https://registry.npmjs.org/@cardstack/upgrade-manager/-/upgrade-manager-1.0.0-beta.tgz","fileCount":309,"integrity":"sha512-Uzpvc1O7qXhwSJcms6R1gC3/dWEBvNvlFkDxeQ58/qxTfHndrkiBlSfp9lWhwdFwzmdYqxrJ/xQNLgmxXiW/7A==","signatures":[{"sig":"MEQCIDLWYPXN9D4NRuO3jq1T8psOf5DpltY/NSKYfX3Zg70DAiAnzSYmMVJ32dL+/zxj3gK+OHcyjjbYU6x1b8TKCT3zVg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1039823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjWayMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrvmQ/+MHNnAwRNoP3nY1CuK85dDeV3z8HeYMlT5nkl8KyYJ3+5B+18\r\n9phbQZBhq08acM4J3DSP/zqFPeWyvYiWFyYYnQxyXu66gpl3a89DFrh86S5d\r\nkVoCKRsss3EE0Osaz/YC2/PQ5MMP0Tq49RW0hoAWzqBV0k9KAOIlh6STwBNt\r\naSw0N9Knih9QHjgDqG3fNgofxfC7ovzcRtMOudw5Y3VGB8Y0f/um8qDK+Fuc\r\nT8WFJKqxcBRXEGlWE1iXEncRG+iSQKSzu0fLjHTKRZW9mo3bGD8OS+lwaflW\r\nPj7U0aHmkmmLAWY64JF/aLzF4CAIa1+CEq/tLIWPM53RBeTsT6z09GlKb/Je\r\nMLE38AuhRy2JJGPHiyIdESOK05zOkgNa6HVNAL7+dur/ecVDC1FBvD9O+QYA\r\nGBRgFNmcEMoRELqtiXE20AkDJPb5YES3grTs6f/pvyYA8+nKhPUOHm/Jeew9\r\nSSNPIdk6B6IX/LZy1YWzYr+cmgkZwKz+jJFBRtGftvTEAu/JM+YeuAy3ZxsZ\r\nqXNKJ7CIj+Y+nrUBAZzE8p8/EKqYmHUwXimh2Mabap3Xv8Eyj4TdJgqOGDGQ\r\nkGdYoGXCooYLzFNkpmOv5Xd5Ronhwv9ZQ+bSwKgVaCDsEv4GsrkZqdIfj4mD\r\ngX5jdQrOARZqwK2zqg0/CHlyY+4gt77WUUc=\r\n=nSxs\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/src/index.js","types":"dist/src/index.d.ts","readme":"# @cardstack/upgrade-manager\n\nThe upgrade manager allows managing a set of smart contracts deployed to a\nchain, handling proxy upgrade and batched configuration application, with\ntooling to support management with a M-of-N gnosis safe.\n\nCurrently supported are OpenZepplin transparent ugpradeable proxy contracts\nand implementations, along with the concept of \"abstract contracts\", which\ncan be used as non-upgradeable implementations for when different proxy\nmechanisms are in use, a common example being Gnosis Safe delegate\nimplementations, or any other custom DELEGATECALL mechanism. \n\n\n## Architecture\n\nThe upgrade manager consists of:\n\n\n### UpgradeManager.sol\n\nA solidity contract that you deploy once  per chain for your hardhat project.\n\nThe UpgradeManager is owned by either an EOA or a Gnosis safe(recommended). It\nbecomes the owner of all your other contracts along with the owner of their\nProxyAdmin contracts.\n\nThis assumes that your upgradeable contracts support this interface:\n```solidity\ninterface Ownable {\n  function owner() public view returns (address);\n  function transferOwnership(address newOwner) public;\n}\n```\n\nOnce the contracts are owned by the upgrade manager, the upgrade manager is\nresponsible for both upgrading their implementation, and calling arbitrary\nconfig methods on them.\n\nTo propose an upgrade or a config method call, or both at the same time, a set\nof upgrade proposers can call the `proposeUpgrade`, `proposeCall`, and\n`proposeUpgradeAndCall` methods respectively. The upgrade proposers can be\naccounts that have a lower level of trust than the upgrade manager owner. For\nexample, on a development team, all the developers could be proposers,\nallowing them to stage changes without those changes taking effect yet.\n\nOnce the upgrades and calls are all proposed, then the owner of the upgrade\nmanager must approve all of these changes. This could be a single EOA but for\nproduction usage, a gnosis safe owner is recommended with a suitable M-of-N\nowner and threshold configuration.\n\nThe changes are applied atomically, so if you have multiple contracts which\ndepend on each other and need to be configured with each others' addresses,\nthere is no point-in-time where your projects contracts are partially\nconfigured or partially upgraded. Either all are upgraded and configured, or\nnone are, from the perspective of any external transaction (note - if you use\ncall or upgradeAndCall, then this may not be true for those internal\ntransactions so you should be careful with what you do in those functions).\n\nThe only limit to the amount of changes that can be applied atomically is the\nblock gas limit, and if the gas usage is too large then changes can be easily\nwithdrawn to reduce gas usage.\n\n### Hardhat plugin\n\nThe hardhat plugin is responsible for handling upgrades and configuration of\nthe contracts in your hardhat project.\n\nYou configure in your hardhat config file a list of the contracts you want to\ndeploy, and you also add a config directory with a js or ts file for each\ncontract you want to configure. When you run the provided `hardhat deploy`\ntask, the plugin will check the current on-chain state and bytecode,\ncompare it to your local code and configuration, and generate the set of\nchanges needed for the blockchain state to be what is required. The scripts\nwill then make the appropriate transactions to the UpgradeManager contract\nto stage these upgrades and configration.\n\nThe current state of your configured contracts can be shown with the\n`hardhat deploy:status` command:\n\n```\n$ hardhat deploy:status\n┌───────────────────────────────┬─────────────────────────┬────────────────────────────────────────────┬────────────────────────────────────────────┬────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────┬────────────────────────┐\n│ Contract ID                   │ Contract Name           │ Proxy Address                              │ Current Implementation Address             │ Proposed Implementation Address            │ Proposed Function Call                                              │ Local Bytecode Changed │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ MockUpgradeableContract       │ MockUpgradeableContract │ 0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 │ 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 │                                            │ setup(                                                              │                        │\n│                               │                         │                                            │                                            │                                            │   string _fooString: \"foo string value\",                            │                        │\n│                               │                         │                                            │                                            │                                            │   address _barAddress: \"0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6\" │                        │\n│                               │                         │                                            │                                            │                                            │ )                                                                   │                        │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ MockUpgradeableSecondInstance │ MockUpgradeableContract │ 0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6 │ 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 │                                            │ setup(                                                              │                        │\n│                               │                         │                                            │                                            │                                            │   string _fooString: \"foo string value second hardhat\",             │                        │\n│                               │                         │                                            │                                            │                                            │   address _barAddress: \"0x5FC8d32690cc91D4c39d9d3abcBD16989F875707\" │                        │\n│                               │                         │                                            │                                            │                                            │ )                                                                   │                        │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ AbstractContract              │ AbstractContract        │                                            │ N/A (proposed)                             │ 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 │                                                                     │ YES                    │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ DeterministicContract         │ AbstractContract        │                                            │ N/A (proposed)                             │ 0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0 │                                                                     │ YES                    │\n└───────────────────────────────┴─────────────────────────┴────────────────────────────────────────────┴────────────────────────────────────────────┴────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────┴────────────────────────┘\n```\n\nThe diff between local / proposed code and on-chain code can also be displayed with the `hardhat deploy:diff:local` and `hardhat deploy:diff:proposed` commands.\n\nIf everything looks good, the upgrade manager owner can use the `hardhat\ndeploy:upgrade` command to execute all proposed changes atomically. If the\nupgrade manager is owned by a gnosis safe, this is automatically detected and\ninstead of submitting the transaction, json with the current and previous\nusers' signatures is output, allowing the next owner to add their signature\nuntil enough are collected to meet the safe's threshold\n\n## Installation\n\n```bash\nnpm install @cardstack/upgrade-manager\n```\n\nImport the plugin in your `hardhat.config.js`:\n\n```js\nrequire(\"@cardstack/upgrade-manager\");\n```\n\nOr if you are using TypeScript, in your `hardhat.config.ts`:\n\n```ts\nimport \"@cardstack/upgrade-manager\";\n```\n\n## Hardhat Configuration\n\nThis plugin extends the `HardhatUserConfig` object with the upgradeManager field.\n\nThis is an example of how to set it:\n\n```js\nmodule.exports = {\n  upgradeManager: {\n    contracts: [\n      \"FooContract\",\n      {\n        id: \"FooContractWithDifferentId\",\n        contract: \"FooContract\",\n      },\n      {\n        id: \"AbstractContract\",\n        abstract: true,\n      },\n      {\n        id: \"DeterministicContract\",\n        contract: \"AbstractContract\",\n        abstract: true,\n        deterministic: true,\n      },\n    ],\n  },\n};\n```\n\n\nEach item in the contracts array can either be a string, to simply deploy an\nupgadeable proxy with the same id as the contract's name, or an object\nrepresenting configuration of the contract. The options are as follows:\n\n* `id`: The arbitrary id you choose to reference this contract. Must be unique.\n* `contract`: The name of the contract from your projects artifacts. You can deploy multiple instances of the same contract with different ids if required\n* `abstract`: Deploy an abstract contract instead of an upgradeable proxy. Abstract contracts do not have config and are intended to be \"implementation only\", so that you can set an implementation for e.g. a safe delegate implementation or another type of DELEGATECALL proxy mechanism\n* `deterministic`: \"Deploy to a stable address based on the contract bytecode using [deterministic-deployment-proxy](https://github.com/Arachnid/deterministic-deployment-proxy). Only supported for abstract contracts\"\n\n\n## Deploy command\n\n\n```\nUsage: hardhat [GLOBAL OPTIONS] deploy [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--dry-run <BOOLEAN>] [--fork <STRING>] [--immediate-config-apply <BOOLEAN>] [--impersonate-address <STRING>]\n\nOPTIONS:\n\n  --auto-confirm            Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path         Derivation path to use when using mnemonic or trezor\n  --dry-run                 Preview what would happen, without actually writing to the blockchain (default: false)\n  --fork                    The network to fork\n  --immediate-config-apply  If there are a large series of calls e.g. during initial setup, apply config immediately by calling methods directly on contracts instead of proposing config changes (default: false)\n  --impersonate-address     Address to impersonate deploying from (usually only makes sense whilst forking)\n\ndeploy: Deploys new contracts and propose implementation and config changes for existing deployed contracts\n```\n\n### Example\n\n```\nhardhat deploy --network goerli\n```\n\n### Forking Example\n\nThis will run the deploy against an in-memory fork so you can preview changes. This assumes you have an rpc url configured correctly for this network in your hardhat config\n\n```\nhardhat deploy --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\n```\n\n\n### Forking with a persistant node\n\nYou may want to preview multiple steps against a fork. To acheive this, first start a forked node:\n\n```sh\nhardhat node --fork $RPC_URL\n```\n\nThen run multiple commands against the forked node:\n\n```sh\nhardhat deploy --network localhost --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\nhardhat deploy:upgrade --network localhost --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\n```\n\n\n## Contract configuration\n\nFor each contract id above that you want to configure, add a file in the `config/` subdirectory of your hardhat project, for example:\n\n```typescript\nimport { ConfigFunction } from \"@cardstack/upgrade-manager/types\";\n\nlet config: ConfigFunction = async function ({ address }) {\n  return {\n    setup: [\n      { getter: \"fooString\", value: \"foo string value\" },\n      {\n        getter: \"barAddress\",\n        value: address(\"MockUpgradeableSecondInstance\"),\n      },\n    ],\n  };\n};\n\nexport default config;\n```\n\nor in javascript:\n\n\n```javascript\nmodule.exports = async function ({ address, deployConfig }) {\n  return {\n    setup: [\n      {\n        getter: \"fooString\",\n        value: `foo string value second ${deployConfig.network}`,\n      },\n      {\n        getter: \"barAddress\",\n        value: address(\"MockUpgradeableContract\"),\n      },\n    ],\n  };\n};\n````\n\nThe keys of the exported objects each represent a config function that should be called on your contract.\n\nThe values for each key is an array of the paramaters to your setup function.\nThe `getter` field is a function to call on your contract to check the current\non-chain value. The `value` field is what the value should be set to after\nconfiguration is complete.\n\nYou can use the `deployConfig.network` field passed in to the config function\nif different configuration is required based on network. The hre is also a\nproperty of deployConfig, so you can switch based on other hardhat\nenvironment settings too.\n\nThis expects roughly the following configuration pattern in your contracts:\n\n```\ncontract MockUpgradeableContract {\n  string public fooString;\n  address public barAddress;\n\n  function setup(string memory _fooString, address _barAddress) external {\n    fooString = _fooString;\n    barAddress = _barAddress;\n  }\n}\n\n```\n\nThe reason to use a single setter method instead of a setter for each\nproperty is to avoid contract-bloat with many setter functions. Usually this\nwould be inconvenient to manually manager, however with the automated\nconfiguration provided by the UpgradeManager this optimisation is no longer\ninconvenient to use\n\n## Testing\n\nRunning `yarn test` will run the solidity tests along with the plugin tests\n\n## Linting and autoformat\n\nYou can check if your code style is correct by running `yarn lint`, and fix\nit with `yarn lint:fix`.\n\n","scripts":{"lint":"yarn lint:js && yarn lint:sol && yarn lint:contract-size","test":"yarn test:sol && yarn test:plugin && yarn lint","build":"yarn compile && node_modules/.bin/tsc && cp *.sol.json ./dist/","clean":"./node_modules/.bin/hardhat clean","watch":"tsc -w","compile":" ./node_modules/.bin/hardhat compile && ./node_modules/.bin/hardhat run ./src/copy-compilation-result.ts","lint:js":"./node_modules/.bin/eslint --max-warnings 0 .","coverage":"env SILENCE_COMPILER_WARNINGS=true ./node_modules/.bin/hardhat coverage","lint:sol":"./node_modules/.bin/solhint ./contracts/\\*\\*/\\*.sol -w 0","test:sol":"./node_modules/.bin/hardhat test --typecheck","recompile":"yarn clean && yarn compile","test:plugin":"yarn build && mocha $INSPECT_FLAG --exit --recursive 'plugin-tests/**/*.test.ts'","prepublishOnly":"yarn clean && yarn build","lint:contract-size":"{ ./node_modules/.bin/hardhat size-contracts | tee /dev/fd/3 | grep -q 'exceed the size limit for mainnet deployment' && exit 1; } 3>&1 || echo 'All contracts within size limit'","test:plugin:inspect":"env INSPECT_FLAG='--inspect-brk' yarn test:plugin"},"_npmUser":{"name":"alex-cs","email":"alex.speller@cardstack.com"},"repository":{"url":"https://github.com/cardstack/upgrade-manager.git","type":"git"},"description":"Cardstack Smart Contract Upgrade Manager","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2022 Cardstack\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","dependencies":{"colors":"^1.4.0","lodash":"^4.17.21","enquirer":"^2.3.6","fs-extra":"^10.1.0","cli-table3":"^0.6.3","cpr-promise":"^0.2.6","trezor-cli-wallet-provider":"^1.0.7","@openzeppelin/hardhat-upgrades":"^1.21.0","@openzeppelin/contracts-upgradeable":"^4.8.0-rc.1","@nomicfoundation/hardhat-network-helpers":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"chai":"^4.2.0","rmrf":"^2.0.4","mocha":"^7.1.2","eslint":"^8.24.0","ethers":"^5.7.2","hardhat":"^2.12.0","solhint":"^3.3.7","ts-node":"^8.1.0","prettier":"^2.7.1","typechain":"^8.1.0","typescript":"^4.0.3","@types/chai":"^4.1.7","@types/node":"^8.10.38","@types/mocha":"^5.2.6","test-console":"^2.0.0","@types/lodash":"^4.14.186","@types/fs-extra":"^5.0.4","chai-as-promised":"^7.1.1","solidity-coverage":"^0.8.1","@typechain/hardhat":"^6.1.2","@types/test-console":"^2.0.0","@typechain/ethers-v5":"^10.1.0","eslint-plugin-import":"^2.26.0","hardhat-gas-reporter":"^1.0.8","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","hardhat-contract-sizer":"^2.6.1","@ethersproject/providers":"^5.4.7","prettier-plugin-solidity":"^1.0.0-beta.24","@nomiclabs/hardhat-ethers":"^2.0.0","@typescript-eslint/parser":"^5.38.1","@nomiclabs/hardhat-etherscan":"^3.0.0","@nomicfoundation/hardhat-toolbox":"^2.0.0","@typescript-eslint/eslint-plugin":"^5.38.1","@nomicfoundation/hardhat-chai-matchers":"^1.0.0"},"peerDependencies":{"hardhat":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-manager_1.0.0-beta_1666821260475_0.40541933168625244","host":"s3://npm-registry-packages"}},"1.0.0":{"name":"@cardstack/upgrade-manager","version":"1.0.0","keywords":["ethereum","smart-contracts","hardhat","hardhat-plugin"],"author":{"name":"Cardstack"},"license":"MIT","_id":"@cardstack/upgrade-manager@1.0.0","maintainers":[{"name":"alex-cs","email":"alex.speller@cardstack.com"},{"name":"pcjun97","email":"pcjun97@gmail.com"},{"name":"jurgen","email":"matic@jurglic.si"},{"name":"burcunoyan","email":"burcu.noyan@cardstack.com"},{"name":"ef4","email":"edward@eaf4.com"},{"name":"habdelra","email":"hassan.abdelrahman@gmail.com"},{"name":"lukemelia","email":"luke@lukemelia.com"},{"name":"aierie","email":"michael.khor@cardstack.com"}],"dist":{"shasum":"03747e78c890307f0d91b66a89176356b7cbc62f","tarball":"https://registry.npmjs.org/@cardstack/upgrade-manager/-/upgrade-manager-1.0.0.tgz","fileCount":515,"integrity":"sha512-73h/hiGGd9KkZbIXFS0SJUF65SF750ogTj4ai4gnPRc7JV3buNaJ1J4LcKqM5aPPR0wKsxkpj82Dz+n6J7ADIg==","signatures":[{"sig":"MEUCIHGsd65giN1bdbmCZEgSByaBlNGhLkBzn5lrJpGMzSY5AiEAzdBMAugsY2vuTFJjYbWafDSgNSiYV0TE7XW6xl7CybE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1697718,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjmOqjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrZFw/9EHXMauoVDTpXqAGkNX2Rja2i4JTFJ4DhAe0sswvhkwcXB4zM\r\n+vDHVZ9l2f8a+6/Jcwx2tmHXkyaPCo0+u4sE5tF/md89DPTZXjZG3sLZ1GGi\r\nfXGw8J65/eRN6F00zW1xR+XCFZTbTxd/XcImbIL4Aio8q3pf3SjXYqIctp9K\r\nyCM6LytEe7fkmHcLv2ZSTm9Zii8vYtOYpnVoWMyfH0rPLXqKV1skL1i5oty+\r\n4O2quddtOFw28GAhek1oMu5kFJg0mJ7kzGawcicPZ/NDhdW8+2u3IokyIHad\r\ngSdyP6ERCwQOP2DJ4IJj0CiDf+fnplk5taanthcoZ54432pc52CDRHcl/EdS\r\nd10PH+/PNQkNY/vqEIEhFfVJaQcmc3e3fegVqdGCHdYTtioMt1O8dQbn2ilh\r\nb+Expjq631FEMdJo3R95L70/xaRqpKJc/UF3YklZ3gRteaLWnq+vqU2mMw6i\r\naV4r7p9u1IELJ63baNYNV59EDM3FhPArfQfCkamDrTvphscAp3TS4pAGM0yJ\r\n90nHYpU8Pe1BClGSetzpztjFg8MSuUtF8ImHvObpXzYdSucwHbi9RY1x9ipp\r\nmxomY3Uzpprf+E6nzV8VmjCA2fnKO695nL//FpLxrJBkQeQYPFcYTUnPEKln\r\nnQ6fSdaN/O5YQ+GTG7y3IY+2SpN0M4CwzL0=\r\n=IxBP\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/src/index.js","types":"dist/src/index.d.ts","scripts":{"lint":"yarn lint:js && yarn lint:sol && yarn lint:contract-size","test":"yarn test:sol && yarn test:plugin && yarn lint","build":"yarn compile && node_modules/.bin/tsc && cp *.sol.json ./dist/","clean":"./node_modules/.bin/hardhat clean","watch":"tsc -w","compile":" ./node_modules/.bin/hardhat compile && ./node_modules/.bin/hardhat run ./src/copy-compilation-result.ts","lint:js":"./node_modules/.bin/eslint --max-warnings 0 .","coverage":"env SILENCE_COMPILER_WARNINGS=true ./node_modules/.bin/hardhat coverage","lint:sol":"./node_modules/.bin/solhint ./contracts/\\*\\*/\\*.sol -w 0","test:sol":"./node_modules/.bin/hardhat test --typecheck","recompile":"yarn clean && yarn compile","test:plugin":"yarn build && mocha $INSPECT_FLAG --exit --recursive 'plugin-tests/**/*.test.ts'","prepublishOnly":"yarn clean && yarn build","lint:contract-size":"{ ./node_modules/.bin/hardhat size-contracts | tee /dev/fd/3 | grep -q 'exceed the size limit for mainnet deployment' && exit 1; } 3>&1 || echo 'All contracts within size limit'","test:plugin:inspect":"env INSPECT_FLAG='--inspect-brk' yarn test:plugin"},"_npmUser":{"name":"alex-cs","email":"alex.speller@cardstack.com"},"repository":{"url":"https://github.com/cardstack/upgrade-manager.git","type":"git"},"description":"Cardstack Smart Contract Upgrade Manager","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2022 Cardstack\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","dependencies":{"colors":"^1.4.0","lodash":"^4.17.21","enquirer":"^2.3.6","fs-extra":"^10.1.0","cli-table3":"^0.6.3","evm-chains":"^0.2.0","cpr-promise":"^0.2.6","@gnosis.pm/safe-contracts":"^1.3.0","trezor-cli-wallet-provider":"^1.0.7","@gnosis.pm/safe-deployments":"^1.0.0","@openzeppelin/hardhat-upgrades":"^1.21.0","@openzeppelin/contracts-upgradeable":"^4.8.0-rc.1","@nomicfoundation/hardhat-network-helpers":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.2.0","rmrf":"^2.0.4","mocha":"^7.1.2","eslint":"^8.24.0","ethers":"^5.7.2","hardhat":"^2.12.0","solhint":"^3.3.7","ts-node":"^8.1.0","prettier":"^2.7.1","typechain":"^8.1.0","typescript":"^4.0.3","@types/chai":"^4.1.7","@types/node":"^8.10.38","@types/mocha":"^5.2.6","test-console":"^2.0.0","@types/lodash":"^4.14.186","@types/fs-extra":"^5.0.4","chai-as-promised":"^7.1.1","solidity-coverage":"^0.8.1","@typechain/hardhat":"^6.1.2","@types/test-console":"^2.0.0","@typechain/ethers-v5":"^10.1.0","eslint-plugin-import":"^2.26.0","hardhat-gas-reporter":"^1.0.8","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","hardhat-contract-sizer":"^2.6.1","@ethersproject/providers":"^5.4.7","prettier-plugin-solidity":"^1.0.0-beta.24","@nomiclabs/hardhat-ethers":"^2.0.0","@typescript-eslint/parser":"^5.38.1","@nomiclabs/hardhat-etherscan":"^3.0.0","@nomicfoundation/hardhat-toolbox":"^2.0.0","@typescript-eslint/eslint-plugin":"^5.38.1","@nomicfoundation/hardhat-chai-matchers":"^1.0.0"},"peerDependencies":{"hardhat":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-manager_1.0.0_1670965923053_0.5158848813925854","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"@cardstack/upgrade-manager","version":"1.0.1","keywords":["ethereum","smart-contracts","hardhat","hardhat-plugin"],"author":{"name":"Cardstack"},"license":"MIT","_id":"@cardstack/upgrade-manager@1.0.1","maintainers":[{"name":"alex-cs","email":"alex.speller@cardstack.com"},{"name":"pcjun97","email":"pcjun97@gmail.com"},{"name":"jurgen","email":"matic@jurglic.si"},{"name":"burcunoyan","email":"burcu.noyan@cardstack.com"},{"name":"ef4","email":"edward@eaf4.com"},{"name":"habdelra","email":"hassan.abdelrahman@gmail.com"},{"name":"lukemelia","email":"luke@lukemelia.com"}],"dist":{"shasum":"24f8990aecf59be051d4e3cf574449d845774b9a","tarball":"https://registry.npmjs.org/@cardstack/upgrade-manager/-/upgrade-manager-1.0.1.tgz","fileCount":515,"integrity":"sha512-79ulfEWLwcfuEg8tVZYouMFoOejobsta+fuKNXG2BjNSBgIKYaeY4HvsFRtPjeTPPkc4C29iInsS2Wl6s8CO7g==","signatures":[{"sig":"MEQCIHYBk9eEfTvSpShEWVtGNnpGMZboCLQUF6+7A66DnGJmAiAlRN4UvZatsaOwR8k+SFoeky0bQkZymPEo3ST4fJMD6A==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1700198,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj4NeeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmokZw/8DQ6HMqtC54xk1DtApHhwvQuyf4r2oQrVWx/QX2H+vV2uQLz5\r\nnw3If2dvP7tcuAEozc2yGMUOziSAxeSnfYK7ijqlSKVufeCTYNJUeqG/1XjF\r\nEwT91AoedWN3xKSXyUBZdI93gmNaNjO9t/Kvym/GcldTvJ5/Sd517ZtacH5w\r\nyw3JJLWAFAy6E734Urf/gChv36wB7Ld2uPdBzQgzBgA6Ciqv3P/RRMLGq3cg\r\nNjA6EeOzmzjXSOaxysZoaQPEWQdPnIKuJcxoYQIY4tTBZqhw/+FXcA4+GmgX\r\nwmIFyRmzRAigNesS7G+SvrzC9a6KREK6vITqvdHvi+oFhlU2AscxpGMJdqJP\r\nHxtyPPk4Mh02q2v0BWJiJ6byW5T5R7Wj9GMkAASVM7ysBRJ0lX3Ta9iORRN/\r\nCg/3EJPY0q8UK3SH7M9aRadULi8xohP6U4lByPuObxWTu0E5gj7QSONb/Nce\r\ne9HpLbx2kDX/GSTGu/g+cx7hZWkZdjEEfzLYge5I5TLNN74Y9DHG90wL+UrN\r\nXZj/TVoKBun10kxmWpND+qkqbngFOSGVRFfZnKZEiFc+1a+lnXFDxHG1T6Sw\r\noIIRZm0d1+Jrli/9Yi2XlPr7JQfgRGmRmQ8HkxrCy5VKRFhqQYvVCtZY47Zz\r\nYX6hDv0OlNdLg9X1tpjT1sbEjWVpqviaVn4=\r\n=6enI\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/src/index.js","types":"dist/src/index.d.ts","scripts":{"lint":"yarn lint:js && yarn lint:sol && yarn lint:contract-size","test":"yarn test:sol && yarn test:plugin && yarn lint","build":"yarn compile && node_modules/.bin/tsc && cp *.sol.json ./dist/","clean":"./node_modules/.bin/hardhat clean","watch":"tsc -w","compile":" ./node_modules/.bin/hardhat compile && ./node_modules/.bin/hardhat run ./src/copy-compilation-result.ts","lint:js":"./node_modules/.bin/eslint --max-warnings 0 .","coverage":"env SILENCE_COMPILER_WARNINGS=true ./node_modules/.bin/hardhat coverage","lint:sol":"./node_modules/.bin/solhint ./contracts/\\*\\*/\\*.sol -w 0","test:sol":"./node_modules/.bin/hardhat test --typecheck","recompile":"yarn clean && yarn compile","test:plugin":"yarn build && mocha $INSPECT_FLAG --exit --recursive 'plugin-tests/**/*.test.ts'","prepublishOnly":"yarn clean && yarn build","lint:contract-size":"{ ./node_modules/.bin/hardhat size-contracts | tee /dev/fd/3 | grep -q 'exceed the size limit for mainnet deployment' && exit 1; } 3>&1 || echo 'All contracts within size limit'","test:plugin:inspect":"env INSPECT_FLAG='--inspect-brk' yarn test:plugin"},"_npmUser":{"name":"alex-cs","email":"alex.speller@cardstack.com"},"repository":{"url":"https://github.com/cardstack/upgrade-manager.git","type":"git"},"description":"Cardstack Smart Contract Upgrade Manager","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2022 Cardstack\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","dependencies":{"colors":"^1.4.0","lodash":"^4.17.21","enquirer":"^2.3.6","fs-extra":"^10.1.0","cli-table3":"^0.6.3","evm-chains":"^0.2.0","cpr-promise":"^0.2.6","@gnosis.pm/safe-contracts":"^1.3.0","trezor-cli-wallet-provider":"^1.0.7","@gnosis.pm/safe-deployments":"^1.0.0","@openzeppelin/hardhat-upgrades":"^1.21.0","@openzeppelin/contracts-upgradeable":"^4.8.0-rc.1","@nomicfoundation/hardhat-network-helpers":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.2.0","rmrf":"^2.0.4","mocha":"^7.1.2","eslint":"^8.24.0","ethers":"^5.7.2","hardhat":"^2.12.0","solhint":"^3.3.7","ts-node":"^8.1.0","prettier":"^2.7.1","typechain":"^8.1.0","typescript":"^4.0.3","@types/chai":"^4.1.7","@types/node":"^8.10.38","@types/mocha":"^5.2.6","test-console":"^2.0.0","@types/lodash":"^4.14.186","@types/fs-extra":"^5.0.4","chai-as-promised":"^7.1.1","solidity-coverage":"^0.8.1","@typechain/hardhat":"^6.1.2","@types/test-console":"^2.0.0","@typechain/ethers-v5":"^10.1.0","eslint-plugin-import":"^2.26.0","hardhat-gas-reporter":"^1.0.8","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","hardhat-contract-sizer":"^2.6.1","@ethersproject/providers":"^5.4.7","prettier-plugin-solidity":"^1.0.0-beta.24","@nomiclabs/hardhat-ethers":"^2.0.0","@typescript-eslint/parser":"^5.38.1","@nomiclabs/hardhat-etherscan":"^3.0.0","@nomicfoundation/hardhat-toolbox":"^2.0.0","@typescript-eslint/eslint-plugin":"^5.38.1","@nomicfoundation/hardhat-chai-matchers":"^1.0.0"},"peerDependencies":{"hardhat":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-manager_1.0.1_1675679645947_0.6204526738059983","host":"s3://npm-registry-packages"}}},"time":{"created":"2022-10-26T21:52:05.496Z","modified":"2026-04-17T13:44:24.138Z","1.0.0-0":"2022-10-26T21:52:05.760Z","1.0.0-beta":"2022-10-26T21:54:20.653Z","1.0.0":"2022-12-13T21:12:03.352Z","1.0.1":"2023-02-06T10:34:06.250Z"},"author":{"name":"Cardstack"},"license":"MIT","keywords":["ethereum","smart-contracts","hardhat","hardhat-plugin"],"repository":{"url":"https://github.com/cardstack/upgrade-manager.git","type":"git"},"description":"Cardstack Smart Contract Upgrade Manager","maintainers":[{"email":"burcu.noyan@cardstack.com","name":"burcunoyan"},{"email":"edward@eaf4.com","name":"ef4"},{"email":"hassan.abdelrahman@gmail.com","name":"habdelra"},{"email":"luke@lukemelia.com","name":"lukemelia"},{"email":"matic@jurglic.si","name":"jurgen"},{"email":"pcjun97@gmail.com","name":"pcjun97"},{"email":"b@chromatin.ca","name":"backspace"},{"email":"justinthong93@gmail.com","name":"tintinthong"},{"email":"fadhlan.ridhwanallah@cardstack.com","name":"fadhlanr"},{"email":"ian.calvert@cardstack.com","name":"iancalcardstack"}],"readme":"# @cardstack/upgrade-manager\n\nThe upgrade manager allows managing a set of smart contracts deployed to a\nchain, handling proxy upgrade and batched configuration application, with\ntooling to support management with a M-of-N gnosis safe.\n\nCurrently supported are OpenZepplin transparent ugpradeable proxy contracts\nand implementations, along with the concept of \"abstract contracts\", which\ncan be used as non-upgradeable implementations for when different proxy\nmechanisms are in use, a common example being Gnosis Safe delegate\nimplementations, or any other custom DELEGATECALL mechanism. \n\n\n## Architecture\n\nThe upgrade manager consists of:\n\n\n### UpgradeManager.sol\n\nA solidity contract that you deploy once  per chain for your hardhat project.\n\nThe UpgradeManager is owned by either an EOA or a Gnosis safe(recommended). It\nbecomes the owner of all your other contracts along with the owner of their\nProxyAdmin contracts.\n\nThis assumes that your upgradeable contracts support this interface:\n```solidity\ninterface Ownable {\n  function owner() public view returns (address);\n  function transferOwnership(address newOwner) public;\n}\n```\n\nOnce the contracts are owned by the upgrade manager, the upgrade manager is\nresponsible for both upgrading their implementation, and calling arbitrary\nconfig methods on them.\n\nTo propose an upgrade or a config method call, or both at the same time, a set\nof upgrade proposers can call the `proposeUpgrade`, `proposeCall`, and\n`proposeUpgradeAndCall` methods respectively. The upgrade proposers can be\naccounts that have a lower level of trust than the upgrade manager owner. For\nexample, on a development team, all the developers could be proposers,\nallowing them to stage changes without those changes taking effect yet.\n\nOnce the upgrades and calls are all proposed, then the owner of the upgrade\nmanager must approve all of these changes. This could be a single EOA but for\nproduction usage, a gnosis safe owner is recommended with a suitable M-of-N\nowner and threshold configuration.\n\nThe changes are applied atomically, so if you have multiple contracts which\ndepend on each other and need to be configured with each others' addresses,\nthere is no point-in-time where your projects contracts are partially\nconfigured or partially upgraded. Either all are upgraded and configured, or\nnone are, from the perspective of any external transaction (note - if you use\ncall or upgradeAndCall, then this may not be true for those internal\ntransactions so you should be careful with what you do in those functions).\n\nThe only limit to the amount of changes that can be applied atomically is the\nblock gas limit, and if the gas usage is too large then changes can be easily\nwithdrawn to reduce gas usage.\n\n### Hardhat plugin\n\nThe hardhat plugin is responsible for handling upgrades and configuration of\nthe contracts in your hardhat project.\n\nYou configure in your hardhat config file a list of the contracts you want to\ndeploy, and you also add a config directory with a js or ts file for each\ncontract you want to configure. When you run the provided `hardhat deploy`\ntask, the plugin will check the current on-chain state and bytecode,\ncompare it to your local code and configuration, and generate the set of\nchanges needed for the blockchain state to be what is required. The scripts\nwill then make the appropriate transactions to the UpgradeManager contract\nto stage these upgrades and configration.\n\nThe current state of your configured contracts can be shown with the\n`hardhat deploy:status` command:\n\n```\n$ hardhat deploy:status\n┌───────────────────────────────┬─────────────────────────┬────────────────────────────────────────────┬────────────────────────────────────────────┬────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────┬────────────────────────┐\n│ Contract ID                   │ Contract Name           │ Proxy Address                              │ Current Implementation Address             │ Proposed Implementation Address            │ Proposed Function Call                                              │ Local Bytecode Changed │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ MockUpgradeableContract       │ MockUpgradeableContract │ 0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 │ 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 │                                            │ setup(                                                              │                        │\n│                               │                         │                                            │                                            │                                            │   string _fooString: \"foo string value\",                            │                        │\n│                               │                         │                                            │                                            │                                            │   address _barAddress: \"0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6\" │                        │\n│                               │                         │                                            │                                            │                                            │ )                                                                   │                        │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ MockUpgradeableSecondInstance │ MockUpgradeableContract │ 0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6 │ 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 │                                            │ setup(                                                              │                        │\n│                               │                         │                                            │                                            │                                            │   string _fooString: \"foo string value second hardhat\",             │                        │\n│                               │                         │                                            │                                            │                                            │   address _barAddress: \"0x5FC8d32690cc91D4c39d9d3abcBD16989F875707\" │                        │\n│                               │                         │                                            │                                            │                                            │ )                                                                   │                        │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ AbstractContract              │ AbstractContract        │                                            │ N/A (proposed)                             │ 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 │                                                                     │ YES                    │\n├───────────────────────────────┼─────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤\n│ DeterministicContract         │ AbstractContract        │                                            │ N/A (proposed)                             │ 0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0 │                                                                     │ YES                    │\n└───────────────────────────────┴─────────────────────────┴────────────────────────────────────────────┴────────────────────────────────────────────┴────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────┴────────────────────────┘\n```\n\nThe diff between local / proposed code and on-chain code can also be displayed with the `hardhat deploy:diff:local` and `hardhat deploy:diff:proposed` commands.\n\nIf everything looks good, the upgrade manager owner can use the `hardhat\ndeploy:upgrade` command to execute all proposed changes atomically. If the\nupgrade manager is owned by a gnosis safe, this is automatically detected and\ninstead of submitting the transaction, json with the current and previous\nusers' signatures is output, allowing the next owner to add their signature\nuntil enough are collected to meet the safe's threshold\n\n## Installation\n\n```bash\nnpm install @cardstack/upgrade-manager\n```\n\nImport the plugin in your `hardhat.config.js`:\n\n```js\nrequire(\"@cardstack/upgrade-manager\");\n```\n\nOr if you are using TypeScript, in your `hardhat.config.ts`:\n\n```ts\nimport \"@cardstack/upgrade-manager\";\n```\n\n## Hardhat Configuration\n\nThis plugin extends the `HardhatUserConfig` object with the upgradeManager field.\n\nThis is an example of how to set it:\n\n```js\nmodule.exports = {\n  upgradeManager: {\n    contracts: [\n      \"FooContract\",\n      {\n        id: \"FooContractWithDifferentId\",\n        contract: \"FooContract\",\n      },\n      {\n        id: \"AbstractContract\",\n        abstract: true,\n      },\n      {\n        id: \"DeterministicContract\",\n        contract: \"AbstractContract\",\n        abstract: true,\n        deterministic: true,\n      },\n    ],\n  },\n};\n```\n\n\nEach item in the contracts array can either be a string, to simply deploy an\nupgadeable proxy with the same id as the contract's name, or an object\nrepresenting configuration of the contract. The options are as follows:\n\n* `id`: The arbitrary id you choose to reference this contract. Must be unique.\n* `contract`: The name of the contract from your projects artifacts. You can deploy multiple instances of the same contract with different ids if required\n* `abstract`: Deploy an abstract contract instead of an upgradeable proxy. Abstract contracts do not have config and are intended to be \"implementation only\", so that you can set an implementation for e.g. a safe delegate implementation or another type of DELEGATECALL proxy mechanism\n* `deterministic`: \"Deploy to a stable address based on the contract bytecode using [deterministic-deployment-proxy](https://github.com/Arachnid/deterministic-deployment-proxy). Only supported for abstract contracts\"\n\n\n## Deploy command\n\n\n```\nUsage: hardhat [GLOBAL OPTIONS] deploy [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--dry-run <BOOLEAN>] [--fork <STRING>] [--immediate-config-apply <BOOLEAN>] [--impersonate-address <STRING>]\n\nOPTIONS:\n\n  --auto-confirm            Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path         Derivation path to use when using mnemonic or trezor\n  --dry-run                 Preview what would happen, without actually writing to the blockchain (default: false)\n  --fork                    The network to fork\n  --immediate-config-apply  If there are a large series of calls e.g. during initial setup, apply config immediately by calling methods directly on contracts instead of proposing config changes (default: false)\n  --impersonate-address     Address to impersonate deploying from (usually only makes sense whilst forking)\n\ndeploy: Deploys new contracts and propose implementation and config changes for existing deployed contracts\n```\n\n### Example\n\n```\nhardhat deploy --network goerli\n```\n\n### Forking Example\n\nThis will run the deploy against an in-memory fork so you can preview changes. This assumes you have an rpc url configured correctly for this network in your hardhat config\n\n```\nhardhat deploy --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\n```\n\n\n### Forking with a persistant node\n\nYou may want to preview multiple steps against a fork. To acheive this, first start a forked node:\n\n```sh\nhardhat node --fork $RPC_URL\n```\n\nThen run multiple commands against the forked node:\n\n```sh\nhardhat deploy --network localhost --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\nhardhat deploy:upgrade --network localhost --fork goerli --impersonate-address $UPGRADE_MANAGER_OWNER_ADDRESS\n```\n\n\n## `deploy:upgrade` command\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:upgrade [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--prior-signatures <STRING>] newVersion\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  newVersion  The new version number to set on the upgrade manager. Does not have to increase or change\n\ndeploy:upgrade: Applies pending contract upgrades and config changes atomically\n\n\n## Contract configuration\n\nFor each contract id above that you want to configure, add a file in the `config/` subdirectory of your hardhat project, for example:\n\n```typescript\nimport { ConfigFunction } from \"@cardstack/upgrade-manager/types\";\n\nlet config: ConfigFunction = async function ({ address }) {\n  return {\n    setup: [\n      { getter: \"fooString\", value: \"foo string value\" },\n      {\n        getter: \"barAddress\",\n        value: address(\"MockUpgradeableSecondInstance\"),\n      },\n    ],\n  };\n};\n\nexport default config;\n```\n\nor in javascript:\n\n\n```javascript\nmodule.exports = async function ({ address, deployConfig }) {\n  return {\n    setup: [\n      {\n        getter: \"fooString\",\n        value: `foo string value second ${deployConfig.network}`,\n      },\n      {\n        getter: \"barAddress\",\n        value: address(\"MockUpgradeableContract\"),\n      },\n    ],\n  };\n};\n````\n\nThe keys of the exported objects each represent a config function that should be called on your contract.\n\nThe values for each key is an array of the paramaters to your setup function.\nThe `getter` field is a function to call on your contract to check the current\non-chain value. The `value` field is what the value should be set to after\nconfiguration is complete.\n\nYou can use the `deployConfig.network` field passed in to the config function\nif different configuration is required based on network. The hre is also a\nproperty of deployConfig, so you can switch based on other hardhat\nenvironment settings too.\n\nThis expects roughly the following configuration pattern in your contracts:\n\n```\ncontract MockUpgradeableContract {\n  string public fooString;\n  address public barAddress;\n\n  function setup(string memory _fooString, address _barAddress) external {\n    fooString = _fooString;\n    barAddress = _barAddress;\n  }\n}\n\n```\n\nThe reason to use a single setter method instead of a setter for each\nproperty is to avoid contract-bloat with many setter functions. Usually this\nwould be inconvenient to manually manage, however with the automated\nconfiguration provided by the UpgradeManager this optimisation is no longer\ninconvenient to use\n\n\n## Adding and removing upgrade proposers\n\n### deploy:add-proposer\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:add-proposer [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--prior-signatures <STRING>] proposerAddress\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  proposerAddress The proposer address to add\n\ndeploy:add-proposer: Adds a proposer\n\n### deploy:remove-proposer\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:remove-proposer [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--prior-signatures <STRING>] proposerAddress\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  proposerAddress The proposer address to remove\n\ndeploy:remove-proposer: Removes a proposer\n\n## Gnosis Safe Ownership of upgrade manager\n\nIt is recommended that after initial deploy, you transfer ownership of the upgrade manager to a gnosis safe.\n\n\n### deploy:safe-setup\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:safe-setup [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--prior-signatures <STRING>] newSafeOwners [newSafeThreshold]\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  newSafeOwners     The new owners of the safe, comma seperated addresses\n  newSafeThreshold  The new threshold for the safe (default: 1)\n\ndeploy:safe-setup: Setup a new Gnosis Safe contract and transfer ths ownership of the upgrade manager to the new safe\n\n### deploy:add-safe-owner\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:add-safe-owner [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--new-safe-threshold <INT>] [--prior-signatures <STRING>] newSafeOwnerAddress\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --new-safe-threshold  The new threshold for the safe, if it changes\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  newSafeOwnerAddress The safe owner address to add\n\ndeploy:add-safe-owner: Adds a safe owner\n\n### deploy:remove-safe-owner\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:remove-safe-owner [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--new-safe-threshold <INT>] [--prior-signatures <STRING>] removeSafeOwnerAddress\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --new-safe-threshold  The new threshold for the safe, if it changes\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  removeSafeOwnerAddress  The safe owner address to remove\n\ndeploy:remove-safe-owner: Removes a safe owner\n\n### deploy:set-safe-threshold\n\nUsage: hardhat [GLOBAL OPTIONS] deploy:set-safe-threshold [--auto-confirm <BOOLEAN>] [--derivation-path <STRING>] [--fork <STRING>] [--impersonate-address <STRING>] [--mnemonic <STRING>] [--prior-signatures <STRING>] newSafeThreshold\n\nOPTIONS:\n\n  --auto-confirm        Don't ask for confirmation, useful in scripts / tests (default: false)\n  --derivation-path     Derivation path to use when using mnemonic or trezor\n  --fork                The network to fork\n  --impersonate-address Address to impersonate deploying from (usually only makes sense whilst forking)\n  --mnemonic            Mnemonic to use for deploy actions\n  --prior-signatures    Prior safe signatures collected for this operation\n\nPOSITIONAL ARGUMENTS:\n\n  newSafeThreshold  The new threshold for the safe\n\ndeploy:set-safe-threshold: Sets the threshold for a safe\n\n## Testing\n\nRunning `yarn test` will run the solidity tests along with the plugin tests\n\n## Linting and autoformat\n\nYou can check if your code style is correct by running `yarn lint`, and fix\nit with `yarn lint:fix`.\n\n","readmeFilename":"README.md"}