From fa860d5ae66c97992e7d62cd5daaafd8f58854ed Mon Sep 17 00:00:00 2001 From: Asa Oines Date: Fri, 28 Jan 2022 21:51:22 -0500 Subject: [PATCH] Add ImplementationDeployer and ImplementationUpgrader (#31) * Add implmentation deployer and upgrader * Comments * Publish optics-provider --- typescript/optics-deploy/package-lock.json | 430 +----------------- typescript/optics-deploy/package.json | 2 +- .../optics-deploy/src/core/implementation.ts | 118 +++++ typescript/optics-deploy/src/core/upgrade.ts | 69 +++ typescript/optics-deploy/src/upgrade.ts | 103 ----- typescript/optics-provider/package.json | 2 +- .../src/optics/govern/index.ts | 50 +- .../src/optics/govern/utils.ts | 6 +- 8 files changed, 224 insertions(+), 556 deletions(-) create mode 100644 typescript/optics-deploy/src/core/implementation.ts create mode 100644 typescript/optics-deploy/src/core/upgrade.ts delete mode 100644 typescript/optics-deploy/src/upgrade.ts diff --git a/typescript/optics-deploy/package-lock.json b/typescript/optics-deploy/package-lock.json index 48458f545..078af5f25 100644 --- a/typescript/optics-deploy/package-lock.json +++ b/typescript/optics-deploy/package-lock.json @@ -1290,6 +1290,14 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "celo-ethers-provider": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/celo-ethers-provider/-/celo-ethers-provider-0.0.0.tgz", + "integrity": "sha512-fKm4DXyngvjafyFCwjh8WKDrWsC+fJTDDRZEIduC/IiZcp8W5KrrwNoIbi3arv1B8Yd4D4E3nxhmIudfOczVEw==", + "requires": { + "ethers": "^5.4.7" + } + }, "chai": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", @@ -1650,425 +1658,13 @@ } }, "optics-multi-provider-community": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/optics-multi-provider-community/-/optics-multi-provider-community-0.1.22.tgz", - "integrity": "sha512-zZ1l7+VBxrvzCvCXKzqAdEUsd6+grBvu6UIClTLnTLT9hlrfgiCHC6vEYnT2DWVCz7XDjvaMef0Wc71auQ4IlQ==", + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/optics-multi-provider-community/-/optics-multi-provider-community-0.1.25.tgz", + "integrity": "sha512-iZ2MGTyIF7bjhhiqag2c6MY9SuGD2POq8jpke1pRyaUyRQo3Gt5gX0vcH3XN7POYdcjRY/NU6XghvEiEwmdGXQ==", "requires": { "@optics-xyz/ts-interface": "^1.1.0", - "ethers": "^5.4.6" - }, - "dependencies": { - "@ethersproject/abi": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.5.0.tgz", - "integrity": "sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w==", - "requires": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "@ethersproject/abstract-provider": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz", - "integrity": "sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==", - "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz", - "integrity": "sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==", - "requires": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0" - } - }, - "@ethersproject/address": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.5.0.tgz", - "integrity": "sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==", - "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/rlp": "^5.5.0" - } - }, - "@ethersproject/base64": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.5.0.tgz", - "integrity": "sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==", - "requires": { - "@ethersproject/bytes": "^5.5.0" - } - }, - "@ethersproject/basex": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.5.0.tgz", - "integrity": "sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/properties": "^5.5.0" - } - }, - "@ethersproject/bignumber": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.5.0.tgz", - "integrity": "sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "bn.js": "^4.11.9" - } - }, - "@ethersproject/bytes": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz", - "integrity": "sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==", - "requires": { - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/constants": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.5.0.tgz", - "integrity": "sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==", - "requires": { - "@ethersproject/bignumber": "^5.5.0" - } - }, - "@ethersproject/contracts": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.5.0.tgz", - "integrity": "sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg==", - "requires": { - "@ethersproject/abi": "^5.5.0", - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0" - } - }, - "@ethersproject/hash": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.5.0.tgz", - "integrity": "sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==", - "requires": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "@ethersproject/hdnode": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.5.0.tgz", - "integrity": "sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q==", - "requires": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/basex": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/pbkdf2": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/wordlists": "^5.5.0" - } - }, - "@ethersproject/json-wallets": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz", - "integrity": "sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ==", - "requires": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hdnode": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/pbkdf2": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "@ethersproject/keccak256": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.5.0.tgz", - "integrity": "sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "js-sha3": "0.8.0" - } - }, - "@ethersproject/logger": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz", - "integrity": "sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==" - }, - "@ethersproject/networks": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.5.2.tgz", - "integrity": "sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==", - "requires": { - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/pbkdf2": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz", - "integrity": "sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/sha2": "^5.5.0" - } - }, - "@ethersproject/properties": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.5.0.tgz", - "integrity": "sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==", - "requires": { - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/providers": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.5.2.tgz", - "integrity": "sha512-hkbx7x/MKcRjyrO4StKXCzCpWer6s97xnm34xkfPiarhtEUVAN4TBBpamM+z66WcTt7H5B53YwbRj1n7i8pZoQ==", - "requires": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/basex": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "@ethersproject/random": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.5.1.tgz", - "integrity": "sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/rlp": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.5.0.tgz", - "integrity": "sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/sha2": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.5.0.tgz", - "integrity": "sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "hash.js": "1.1.7" - } - }, - "@ethersproject/signing-key": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.5.0.tgz", - "integrity": "sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "@ethersproject/solidity": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.5.0.tgz", - "integrity": "sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw==", - "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "@ethersproject/strings": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.5.0.tgz", - "integrity": "sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/transactions": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.5.0.tgz", - "integrity": "sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==", - "requires": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0" - } - }, - "@ethersproject/units": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.5.0.tgz", - "integrity": "sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag==", - "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "@ethersproject/wallet": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.5.0.tgz", - "integrity": "sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q==", - "requires": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/hdnode": "^5.5.0", - "@ethersproject/json-wallets": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/wordlists": "^5.5.0" - } - }, - "@ethersproject/web": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.5.1.tgz", - "integrity": "sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==", - "requires": { - "@ethersproject/base64": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "@ethersproject/wordlists": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.5.0.tgz", - "integrity": "sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q==", - "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "ethers": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.5.3.tgz", - "integrity": "sha512-fTT4WT8/hTe/BLwRUtl7I5zlpF3XC3P/Xwqxc5AIP2HGlH15qpmjs0Ou78az93b1rLITzXLFxoNX63B8ZbUd7g==", - "requires": { - "@ethersproject/abi": "5.5.0", - "@ethersproject/abstract-provider": "5.5.1", - "@ethersproject/abstract-signer": "5.5.0", - "@ethersproject/address": "5.5.0", - "@ethersproject/base64": "5.5.0", - "@ethersproject/basex": "5.5.0", - "@ethersproject/bignumber": "5.5.0", - "@ethersproject/bytes": "5.5.0", - "@ethersproject/constants": "5.5.0", - "@ethersproject/contracts": "5.5.0", - "@ethersproject/hash": "5.5.0", - "@ethersproject/hdnode": "5.5.0", - "@ethersproject/json-wallets": "5.5.0", - "@ethersproject/keccak256": "5.5.0", - "@ethersproject/logger": "5.5.0", - "@ethersproject/networks": "5.5.2", - "@ethersproject/pbkdf2": "5.5.0", - "@ethersproject/properties": "5.5.0", - "@ethersproject/providers": "5.5.2", - "@ethersproject/random": "5.5.1", - "@ethersproject/rlp": "5.5.0", - "@ethersproject/sha2": "5.5.0", - "@ethersproject/signing-key": "5.5.0", - "@ethersproject/solidity": "5.5.0", - "@ethersproject/strings": "5.5.0", - "@ethersproject/transactions": "5.5.0", - "@ethersproject/units": "5.5.0", - "@ethersproject/wallet": "5.5.0", - "@ethersproject/web": "5.5.1", - "@ethersproject/wordlists": "5.5.0" - } - }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - } + "celo-ethers-provider": "0.0.0", + "ethers": "^5.4.7" } }, "path-is-absolute": { diff --git a/typescript/optics-deploy/package.json b/typescript/optics-deploy/package.json index 1feadce70..71031d9c2 100644 --- a/typescript/optics-deploy/package.json +++ b/typescript/optics-deploy/package.json @@ -27,6 +27,6 @@ "axios": "^0.21.3", "chai": "^4.3.4", "dotenv": "^10.0.0", - "optics-multi-provider-community": "0.1.22" + "optics-multi-provider-community": "^0.1.25" } } diff --git a/typescript/optics-deploy/src/core/implementation.ts b/typescript/optics-deploy/src/core/implementation.ts new file mode 100644 index 000000000..72d7c980e --- /dev/null +++ b/typescript/optics-deploy/src/core/implementation.ts @@ -0,0 +1,118 @@ +import * as proxyUtils from '../proxyUtils'; +import { CoreDeploy } from './CoreDeploy'; +import { writeDeployOutput } from './index'; +import * as contracts from '@optics-xyz/ts-interface/dist/optics-core'; +import { log, warn } from '../utils'; + +export class ImplementationDeployer { + private _deploys: CoreDeploy[]; + + constructor(deploys: CoreDeploy[]) { + this._deploys = deploys; + } + + deployHomeImplementations(): Promise { + return this._deployImplementations(this._deployHomeImplementation) + } + + deployReplicaImplementations(): Promise { + return this._deployImplementations(this._deployReplicaImplementation) + } + + writeDeploys(dir: string): void { + writeDeployOutput(this._deploys, dir); + } + + /** + * Deploys a Home implementation on the chain of the given deploy and updates + * the deploy instance with the new contract. + * + * @param deploy - The deploy instance + */ + private async _deployHomeImplementation(deploy: CoreDeploy) { + const isTestDeploy: boolean = deploy.test; + if (isTestDeploy) warn('deploying test Home'); + const homeFactory = isTestDeploy + ? contracts.TestHome__factory + : contracts.Home__factory; + const implementation = await proxyUtils.deployImplementation( + 'Home', + deploy, + new homeFactory(deploy.deployer), + deploy.chain.domain + ); + + deploy.contracts.home = proxyUtils.overrideBeaconProxyImplementation( + implementation, + deploy, + new homeFactory(deploy.deployer), + deploy.contracts.home! + ); + } + + /** + * Deploys a Replica implementation on the chain of the given deploy and updates + * the deploy instance with the new contracts. + * + * @param deploy - The deploy instance + */ + private async _deployReplicaImplementation(deploy: CoreDeploy) { + const isTestDeploy: boolean = deploy.test; + if (isTestDeploy) warn('deploying test Replica'); + const replicaFactory = isTestDeploy + ? contracts.TestReplica__factory + : contracts.Replica__factory; + const implementation = await proxyUtils.deployImplementation( + 'Replica', + deploy, + new replicaFactory(deploy.deployer), + deploy.chain.domain, + deploy.config.processGas, + deploy.config.reserveGas, + ); + + for (const domain in deploy.contracts.replicas) { + deploy.contracts.replicas[domain] = proxyUtils.overrideBeaconProxyImplementation( + implementation, + deploy, + new replicaFactory(deploy.deployer), + deploy.contracts.replicas[domain] + ); + } + } + + /** + * Deploy a new contract implementation to each chain in the deploys + * array. + * + * @dev The first chain in the array will be the governing chain + * + * @param deploys - An array of chain deploys + * @param deployImplementation - A function that deploys a new implementation + */ + private async _deployImplementations(deployImplementation: (d: CoreDeploy) => void) { + if (this._deploys.length == 0) { + throw new Error('Must pass at least one deploy config'); + } + + // there exists any chain marked test + const isTestDeploy: boolean = this._deploys.filter((c) => c.test).length > 0; + + log(isTestDeploy, `Beginning ${this._deploys.length} Chain deploy process`); + log(isTestDeploy, `Deploy env is ${this._deploys[0].config.environment}`); + log(isTestDeploy, `${this._deploys[0].chain.name} is governing`); + + log(isTestDeploy, 'awaiting provider ready'); + await Promise.all([ + this._deploys.map(async (deploy) => { + await deploy.ready(); + }), + ]); + log(isTestDeploy, 'done readying'); + + // Do it sequentially + for (const deploy of this._deploys) { + await deployImplementation(deploy) + } + } +} diff --git a/typescript/optics-deploy/src/core/upgrade.ts b/typescript/optics-deploy/src/core/upgrade.ts new file mode 100644 index 000000000..a3304b2d3 --- /dev/null +++ b/typescript/optics-deploy/src/core/upgrade.ts @@ -0,0 +1,69 @@ +import { expect } from 'chai'; +import { ProxyNames } from '../proxyUtils'; +import { OpticsContext } from 'optics-multi-provider-community'; +import { CoreDeploy } from './CoreDeploy'; +import { InvariantViolation, InvariantViolationCollector } from '../checks'; +import { checkCoreDeploys } from './checks'; +import { Call, CallBatch } from 'optics-multi-provider-community/dist/optics/govern'; + +export class ImplementationUpgrader { + private _deploys: CoreDeploy[]; + private _context: OpticsContext; + private _violations: InvariantViolation[]; + private _checked: boolean; + + constructor(deploys: CoreDeploy[], context: OpticsContext) { + this._deploys = deploys; + this._context = context; + this._violations = []; + this._checked = false; + } + + async getInvariantViolations(): Promise { + const governorDomain = await this._context.governorDomain() + const invariantViolationCollector = new InvariantViolationCollector() + await checkCoreDeploys( + this._deploys, + governorDomain, + invariantViolationCollector.handleViolation, + ); + this._violations = invariantViolationCollector.violations; + } + + expectViolations(names: ProxyNames[], count: number[]) { + expect(names).to.have.lengthOf(count.length); + names.forEach((name: ProxyNames, i: number) => { + const matches = this._violations.filter((v: InvariantViolation) => v.name === name); + expect(matches).to.have.lengthOf(count[i]); + }) + const unmatched = this._violations.filter((v: InvariantViolation) => names.indexOf(v.name) === -1); + expect(unmatched).to.be.empty; + this._checked = true; + } + + async createCallBatch(): Promise { + if (!this._checked) + throw new Error('Must check invariants match expectation'); + const governorCore = await this._context.governorCore() + const governanceMessages = await governorCore.newGovernanceBatch() + const populate = this._violations.map(async (violation) => { + const upgrade = await violation.upgradeBeaconController.populateTransaction.upgrade( + violation.beaconProxy.beacon.address, + violation.expectedImplementationAddress + ); + if (upgrade.to === undefined) { + throw new Error('Missing "to" field in populated transaction') + } + governanceMessages.push(violation.domain, upgrade as Call) + }) + await Promise.all(populate); + return governanceMessages; + } +} + +export function expectCalls(batch: CallBatch, domains: number[], count: number[]) { + expect(domains).to.have.lengthOf(count.length); + domains.forEach((domain: number, i: number) => { + expect(batch.calls.get(domain)).to.have.lengthOf(count[i]); + }) +} diff --git a/typescript/optics-deploy/src/upgrade.ts b/typescript/optics-deploy/src/upgrade.ts deleted file mode 100644 index 7e5033025..000000000 --- a/typescript/optics-deploy/src/upgrade.ts +++ /dev/null @@ -1,103 +0,0 @@ -import * as proxyUtils from './proxyUtils'; -import { CoreDeploy } from './core/CoreDeploy'; -import { writeDeployOutput } from './core'; -import * as contracts from '@optics-xyz/ts-interface/dist/optics-core'; -import { log, warn } from './utils'; - -/** - * Deploys a Home implementation on the chain of the given deploy and updates - * the deploy instance with the new contract. - * - * @param deploy - The deploy instance - */ -export async function deployHomeImplementation(deploy: CoreDeploy) { - const isTestDeploy: boolean = deploy.test; - if (isTestDeploy) warn('deploying test Home'); - const homeFactory = isTestDeploy - ? contracts.TestHome__factory - : contracts.Home__factory; - const implementation = await proxyUtils.deployImplementation( - 'Home', - deploy, - new homeFactory(deploy.deployer), - deploy.chain.domain - ); - - deploy.contracts.home = proxyUtils.overrideBeaconProxyImplementation( - implementation, - deploy, - new homeFactory(deploy.deployer), - deploy.contracts.home! - ); -} - -/** - * Deploys a Replica implementation on the chain of the given deploy and updates - * the deploy instance with the new contracts. - * - * @param deploy - The deploy instance - */ -export async function deployReplicaImplementation(deploy: CoreDeploy) { - const isTestDeploy: boolean = deploy.test; - if (isTestDeploy) warn('deploying test Replica'); - const replicaFactory = isTestDeploy - ? contracts.TestReplica__factory - : contracts.Replica__factory; - const implementation = await proxyUtils.deployImplementation( - 'Replica', - deploy, - new replicaFactory(deploy.deployer), - deploy.chain.domain, - deploy.config.processGas, - deploy.config.reserveGas, - ); - - for (const domain in deploy.contracts.replicas) { - deploy.contracts.replicas[domain] = proxyUtils.overrideBeaconProxyImplementation( - implementation, - deploy, - new replicaFactory(deploy.deployer), - deploy.contracts.replicas[domain] - ); - } -} - -/** - * Deploy a new contract implementation to each chain in the deploys - * array. - * - * @dev The first chain in the array will be the governing chain - * - * @param deploys - An array of chain deploys - * @param deployImplementation - A function that deploys a new implementation - */ -export async function deployImplementations(dir: string, deploys: CoreDeploy[], deployImplementation: (d: CoreDeploy) => void) { - if (deploys.length == 0) { - throw new Error('Must pass at least one deploy config'); - } - - // there exists any chain marked test - const isTestDeploy: boolean = deploys.filter((c) => c.test).length > 0; - - log(isTestDeploy, `Beginning ${deploys.length} Chain deploy process`); - log(isTestDeploy, `Deploy env is ${deploys[0].config.environment}`); - log(isTestDeploy, `${deploys[0].chain.name} is governing`); - - log(isTestDeploy, 'awaiting provider ready'); - await Promise.all([ - deploys.map(async (deploy) => { - await deploy.ready(); - }), - ]); - log(isTestDeploy, 'done readying'); - - // Do it sequentially - for (const deploy of deploys) { - await deployImplementation(deploy) - } - - // write config outputs again, should write under a different dir - if (!isTestDeploy) { - writeDeployOutput(deploys, dir); - } -} diff --git a/typescript/optics-provider/package.json b/typescript/optics-provider/package.json index 1369c3e93..9c6f0fa7f 100644 --- a/typescript/optics-provider/package.json +++ b/typescript/optics-provider/package.json @@ -1,6 +1,6 @@ { "name": "optics-multi-provider-community", - "version": "0.1.24", + "version": "0.1.25", "description": "multi-provider for Optics", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/typescript/optics-provider/src/optics/govern/index.ts b/typescript/optics-provider/src/optics/govern/index.ts index 9ff5592a4..b5a9e2d97 100644 --- a/typescript/optics-provider/src/optics/govern/index.ts +++ b/typescript/optics-provider/src/optics/govern/index.ts @@ -12,15 +12,13 @@ export interface Call { } export class CallBatch { - readonly local: Readonly[]; - readonly remote: Map[]>; + readonly calls: Map[]>; private core: CoreContracts; private built?: ethers.PopulatedTransaction[]; constructor(core: CoreContracts) { this.core = core; - this.remote = new Map(); - this.local = []; + this.calls = new Map(); } static async fromCore(core: CoreContracts): Promise { @@ -32,45 +30,37 @@ export class CallBatch { return new CallBatch(core); } - pushLocal(call: Call): void { + push(domain: number, call: Call): void { if (this.built) throw new Error('Batch has been built. Cannot push more calls'); - this.local.push(utils.normalizeCall(call)); - } - - pushRemote(domain: number, call: Call): void { - if (this.built) - throw new Error('Batch has been built. Cannot push more calls'); - const calls = this.remote.get(domain); + const calls = this.calls.get(domain); const normalized = utils.normalizeCall(call); if (!calls) { - this.remote.set(domain, [normalized]); + this.calls.set(domain, [normalized]); } else { calls.push(normalized); } } // Build governance transactions from this callbatch - async build( - overrides?: ethers.Overrides, - ): Promise { - if (this.built && overrides) - throw new Error('Cannot rebuild batch with new overrides') + async build(): Promise { if (this.built) return this.built; - const [domains, remoteCalls] = utils.associateRemotes(this.remote); - const local = await this.core.governanceRouter.populateTransaction.callLocal(this.local) - const remotes = await Promise.all( - domains.map((domain: number, i: number) => this.core.governanceRouter.populateTransaction.callRemote(domain, remoteCalls[i], overrides)) + const [domains, calls] = utils.associateCalls(this.calls); + this.built = await Promise.all( + domains.map((domain: number, i: number) => { + if (domain === this.core.domain) { + return this.core.governanceRouter.populateTransaction.callLocal(calls[i]) + } else { + return this.core.governanceRouter.populateTransaction.callRemote(domain, calls[i]) + } + }) ) - this.built = remotes.concat(local) return this.built; } // Sign each governance transaction and dispatch them to the chain - async execute( - overrides?: ethers.Overrides, - ): Promise { - const transactions = await this.build(overrides); + async execute(): Promise { + const transactions = await this.build(); const signer = await this.governorSigner() const receipts = [] for (const tx of transactions) { @@ -80,10 +70,8 @@ export class CallBatch { return receipts } - async estimateGas( - overrides?: ethers.Overrides, - ): Promise { - const transactions = await this.build(overrides); + async estimateGas(): Promise { + const transactions = await this.build(); const signer = await this.governorSigner() const responses = [] for (const tx of transactions) { diff --git a/typescript/optics-provider/src/optics/govern/utils.ts b/typescript/optics-provider/src/optics/govern/utils.ts index 142c9d543..d315f9fe2 100644 --- a/typescript/optics-provider/src/optics/govern/utils.ts +++ b/typescript/optics-provider/src/optics/govern/utils.ts @@ -26,12 +26,12 @@ export function serializeCall(call: Call): string { ); } -export function associateRemotes( - remoteCalls: Map, +export function associateCalls( + _calls: Map, ): [number[], Call[][]] { const domains = []; const calls = []; - for (const [key, value] of remoteCalls) { + for (const [key, value] of _calls) { domains.push(key); calls.push(value); }