diff --git a/.changeset/healthy-zoos-rule.md b/.changeset/healthy-zoos-rule.md new file mode 100644 index 000000000..9ea44dfe8 --- /dev/null +++ b/.changeset/healthy-zoos-rule.md @@ -0,0 +1,5 @@ +--- +'@celo/connect': minor +--- + +Adds isCel2 util function to check for L1/L2 context diff --git a/.changeset/slimy-cups-listen.md b/.changeset/slimy-cups-listen.md new file mode 100644 index 000000000..e365c5477 --- /dev/null +++ b/.changeset/slimy-cups-listen.md @@ -0,0 +1,5 @@ +--- +'@celo/celocli': patch +--- + +Add deprecation notice about future removal of `account:offchain-read` and `account:offchain-write` commands. These were created to showcase ["CIP8: Expand Metadata to general off-chain storage"](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0008.md), which has been abandond and they are presenting a high maintainence burden. diff --git a/.changeset/smooth-pumpkins-develop.md b/.changeset/smooth-pumpkins-develop.md new file mode 100644 index 000000000..54f4d6f8e --- /dev/null +++ b/.changeset/smooth-pumpkins-develop.md @@ -0,0 +1,5 @@ +--- +'@celo/celocli': minor +--- + +Adds support for multisigs (via the `--useMultisig` flag) in the `governance:propose` command. diff --git a/.changeset/tender-lamps-study.md b/.changeset/tender-lamps-study.md new file mode 100644 index 000000000..fbd9e1182 --- /dev/null +++ b/.changeset/tender-lamps-study.md @@ -0,0 +1,5 @@ +--- +'@celo/contractkit': patch +--- + +Nit: Capitalises function name using camel-case (`isowner` -> `isOwner`). diff --git a/.github/actions/upload-codecov/action.yml b/.github/actions/upload-codecov/action.yml new file mode 100644 index 000000000..c69271cb4 --- /dev/null +++ b/.github/actions/upload-codecov/action.yml @@ -0,0 +1,24 @@ +name: "Upload Codecov report" +description: "Fetches Codecov token and uploads report" +inputs: + report-name: + description: "Report name to use while uploading it" + required: false + default: "" +runs: + using: "composite" + steps: + - name: Akeyless Get CODECOV_TOKEN Secrets + id: get_codecov_token + uses: docker://us-west1-docker.pkg.dev/devopsre/akeyless-public/akeyless-action:latest + with: + api-url: https://api.gateway.akeyless.celo-networks-dev.org + access-id: p-kf9vjzruht6l + static-secrets: '{"/static-secrets/dev-tooling-circle/codecov/developer-tooling":"CODECOV_TOKEN"}' + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + verbose: true + name: ${{ inputs.report-name }} + env: + CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3320e8784..2dcdc2b1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -144,6 +144,9 @@ jobs: general_test: name: General jest test runs-on: ['self-hosted', 'org', '8-cpu'] + permissions: # Must change the job token permissions to use Akeyless JWT auth + id-token: write + contents: read needs: install-dependencies steps: - uses: actions/checkout@v4 @@ -160,16 +163,23 @@ jobs: --exclude celo \ --exclude "@celo/{celocli,contractkit,wallet-*}" \ -ip \ - run test + run test --coverage - name: Upload Jest Test Results uses: actions/upload-artifact@v3 with: name: Jest Test Results path: test-results/jest + - uses: ./.github/actions/upload-codecov + with: + report-name: "general_test" + wallet-test: name: Wallet test runs-on: ['self-hosted', 'org', '8-cpu'] timeout-minutes: 30 + permissions: # Must change the job token permissions to use Akeyless JWT auth + id-token: write + contents: read needs: install-dependencies steps: - uses: actions/checkout@v4 @@ -180,12 +190,19 @@ jobs: - run: sudo corepack enable yarn - name: Run Wallet tests run: | - yarn workspaces foreach -ip --all --include '@celo/wallet-*' run test + yarn workspaces foreach -ip --all --include '@celo/wallet-*' run test --coverage + - uses: ./.github/actions/upload-codecov + with: + report-name: "wallet" + contractkit-tests: name: ContractKit Tests runs-on: ['self-hosted', 'org', '8-cpu'] timeout-minutes: 30 + permissions: # Must change the job token permissions to use Akeyless JWT auth + id-token: write + contents: read needs: [install-dependencies] if: | @@ -203,12 +220,18 @@ jobs: - run: sudo corepack enable yarn - name: Run tests run: | - yarn workspace @celo/contractkit test + yarn workspace @celo/contractkit test --coverage + - uses: ./.github/actions/upload-codecov + with: + report-name: "contractkit" cli-tests: name: CeloCli Tests runs-on: ['self-hosted', 'org', '8-cpu'] timeout-minutes: 30 + permissions: # Must change the job token permissions to use Akeyless JWT auth + id-token: write + contents: read needs: [install-dependencies] if: | @@ -227,13 +250,16 @@ jobs: artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - name: Run tests run: | - yarn workspace @celo/celocli test + yarn workspace @celo/celocli test --coverage - name: Verify that a new account can be created run: | yarn workspace @celo/celocli run celocli account:new - name: Test that releasecelo command topic is working run: | yarn workspace @celo/celocli run celocli releasecelo --help + - uses: ./.github/actions/upload-codecov + with: + report-name: "celocli" docs-tests: name: Docs tests diff --git a/packages/cli/src/commands/account/offchain-read.ts b/packages/cli/src/commands/account/offchain-read.ts index ec7d23320..ad0d07998 100644 --- a/packages/cli/src/commands/account/offchain-read.ts +++ b/packages/cli/src/commands/account/offchain-read.ts @@ -1,9 +1,9 @@ import { BasicDataWrapper } from '@celo/identity/lib/offchain-data-wrapper' import { PrivateNameAccessor, PublicNameAccessor } from '@celo/identity/lib/offchain/accessors/name' -import { Flags } from '@oclif/core' +import { Flags, ux } from '@oclif/core' import { BaseCommand } from '../../base' import { CustomArgs, CustomFlags } from '../../utils/command' -import { OffchainDataCommand } from '../../utils/off-chain-data' +import { DEPRECATION_NOTICE, OffchainDataCommand } from '../../utils/off-chain-data' export default class OffchainRead extends BaseCommand { static description = 'DEV: Reads the name from offchain storage' @@ -23,6 +23,8 @@ export default class OffchainRead extends BaseCommand { static examples = ['offchain-read 0x...', 'offchain-read 0x... --from 0x... --privateKey 0x...'] async run() { + ux.warn(DEPRECATION_NOTICE) + const kit = await this.getKit() const { args: { arg1: address }, diff --git a/packages/cli/src/commands/account/offchain-write.ts b/packages/cli/src/commands/account/offchain-write.ts index 42a2d0405..5f934c603 100644 --- a/packages/cli/src/commands/account/offchain-write.ts +++ b/packages/cli/src/commands/account/offchain-write.ts @@ -1,8 +1,8 @@ import { PrivateNameAccessor, PublicNameAccessor } from '@celo/identity/lib/offchain/accessors/name' import { privateKeyToAddress } from '@celo/utils/lib/address' -import { Flags } from '@oclif/core' +import { Flags, ux } from '@oclif/core' import { binaryPrompt } from '../../utils/cli' -import { OffchainDataCommand } from '../../utils/off-chain-data' +import { DEPRECATION_NOTICE, OffchainDataCommand } from '../../utils/off-chain-data' export default class OffchainWrite extends OffchainDataCommand { static description = 'DEV: Writes a name to offchain storage' @@ -24,6 +24,8 @@ export default class OffchainWrite extends OffchainDataCommand { ] async run() { + ux.warn(DEPRECATION_NOTICE) + const kit = await this.getKit() const { flags: { encryptTo, name, privateDEK, privateKey }, diff --git a/packages/cli/src/commands/governance/approve.ts b/packages/cli/src/commands/governance/approve.ts index 2c266555a..caa796ff0 100644 --- a/packages/cli/src/commands/governance/approve.ts +++ b/packages/cli/src/commands/governance/approve.ts @@ -53,7 +53,7 @@ export default class Approve extends BaseCommand { const checkBuilder = newCheckBuilder(this) .isApprover(approver) .addConditionalCheck(`${account} is multisig signatory`, useMultiSig, () => - governanceApproverMultiSig!.isowner(account) + governanceApproverMultiSig!.isOwner(account) ) let governanceTx: CeloTransactionObject diff --git a/packages/cli/src/commands/governance/propose.test.ts b/packages/cli/src/commands/governance/propose.test.ts index 1c65a19d5..779a408a0 100644 --- a/packages/cli/src/commands/governance/propose.test.ts +++ b/packages/cli/src/commands/governance/propose.test.ts @@ -7,6 +7,8 @@ import { ux } from '@oclif/core' import * as fs from 'fs' import Web3 from 'web3' import { EXTRA_LONG_TIMEOUT_MS, testLocally } from '../../test-utils/cliUtils' +import { createMultisig } from '../../test-utils/multisigUtils' +import Approve from '../multisig/approve' import Propose from './propose' process.env.NO_SYNCCHECK = 'true' @@ -205,6 +207,140 @@ testWithGanache('governance:propose cmd', (web3: Web3) => { EXTRA_LONG_TIMEOUT_MS ) + test( + 'will successfully create proposal based on Core contract with multisig (1 signer)', + async () => { + const transactionsToBeSaved = JSON.stringify(transactions) + fs.writeFileSync('transactions.json', transactionsToBeSaved, { flag: 'w' }) + + await ( + await kit.sendTransaction({ + from: accounts[0], + to: governance.address, + value: web3.utils.toWei('1', 'ether'), + }) + ).waitReceipt() + + const multisigWithOneSigner = await createMultisig(kit, [accounts[0]], 1, 1) + /** + * Faucet the multisig with 20,000 CELO so it has more than sufficient CELO + * to submit governance proposals (2x minDeposit in this case). + * In practice, `minDeposit` is currently 1 CELO on the devchain, so practically 20,000 CELO + * is too much. But I'm leaving this in case we update the devchain to match + * Alfajores or Mainnet parameters in the future. + */ + await ( + await kit.sendTransaction({ + from: accounts[2], + to: multisigWithOneSigner, + value: web3.utils.toWei('20000', 'ether'), // 2x min deposit on Mainnet + }) + ).waitReceipt() + + const proposalBefore = await governance.getProposal(1) + expect(proposalBefore).toEqual([]) + + await testLocally(Propose, [ + '--jsonTransactions', + 'transactions.json', + '--deposit', + '10000e18', + '--from', + accounts[0], + '--useMultiSig', + '--for', + multisigWithOneSigner, + '--descriptionURL', + 'https://dummyurl.com', + ]) + + const proposal = await governance.getProposal(1) + expect(proposal.length).toEqual(transactions.length) + expect(proposal[0].to).toEqual(goldToken.address) + expect(proposal[0].value).toEqual(transactions[0].value) + const expectedInput = goldToken['contract'].methods['transfer']( + transactions[0].args[0], + transactions[0].args[1] + ).encodeABI() + expect(proposal[0].input).toEqual(expectedInput) + }, + EXTRA_LONG_TIMEOUT_MS + ) + + test( + 'will successfully create proposal based on Core contract with multisig (2 signers)', + async () => { + const transactionsToBeSaved = JSON.stringify(transactions) + fs.writeFileSync('transactions.json', transactionsToBeSaved, { flag: 'w' }) + + await ( + await kit.sendTransaction({ + to: governance.address, + from: accounts[0], + value: web3.utils.toWei('1', 'ether'), + }) + ).waitReceipt() + + const multisigWithTwoSigners = await createMultisig(kit, [accounts[0], accounts[1]], 2, 2) + /** + * Faucet the multisig with 20,000 CELO so it has more than sufficient CELO + * to submit governance proposals (2x minDeposit in this case). + * In practice, `minDeposit` is currently 1 CELO on the devchain, so practically 20,000 CELO + * is too much. But I'm leaving this in case we update the devchain to match + * Alfajores or Mainnet parameters in the future. + */ + await ( + await kit.sendTransaction({ + from: accounts[2], + to: multisigWithTwoSigners, + value: web3.utils.toWei('20000', 'ether'), // 2x min deposit on Mainnet + }) + ).waitReceipt() + + const proposalBefore = await governance.getProposal(1) + expect(proposalBefore).toEqual([]) + + // Submit proposal from signer A + await testLocally(Propose, [ + '--jsonTransactions', + 'transactions.json', + '--deposit', + '10000e18', + '--from', + accounts[0], + '--useMultiSig', + '--for', + multisigWithTwoSigners, + '--descriptionURL', + 'https://dummyurl.com', + ]) + + const proposalBetween = await governance.getProposal(1) + expect(proposalBetween).toEqual([]) + + // Approve proposal from signer B + await testLocally(Approve, [ + '--from', + accounts[1], + '--for', + multisigWithTwoSigners, + '--tx', + '0', + ]) + + const proposal = await governance.getProposal(1) + expect(proposal.length).toEqual(transactions.length) + expect(proposal[0].to).toEqual(goldToken.address) + expect(proposal[0].value).toEqual(transactions[0].value) + const expectedInput = goldToken['contract'].methods['transfer']( + transactions[0].args[0], + transactions[0].args[1] + ).encodeABI() + expect(proposal[0].input).toEqual(expectedInput) + }, + EXTRA_LONG_TIMEOUT_MS + ) + test( 'will successfully create proposal with random contract', async () => { diff --git a/packages/cli/src/commands/governance/propose.ts b/packages/cli/src/commands/governance/propose.ts index 4fa0e2e73..2bae736cc 100644 --- a/packages/cli/src/commands/governance/propose.ts +++ b/packages/cli/src/commands/governance/propose.ts @@ -1,4 +1,3 @@ -import { StrongAddress } from '@celo/base' import { ProposalBuilder, proposalToJSON, ProposalTransactionJSON } from '@celo/governance' import { Flags } from '@oclif/core' import { BigNumber } from 'bignumber.js' @@ -26,6 +25,13 @@ export default class Propose extends BaseCommand { description: 'Amount of Celo to attach to proposal', }), from: CustomFlags.address({ required: true, description: "Proposer's address" }), + useMultiSig: Flags.boolean({ + description: 'True means the request will be sent through multisig.', + }), + for: CustomFlags.address({ + dependsOn: ['useMultiSig'], + description: 'Address of the multi-sig contract', + }), force: Flags.boolean({ description: 'Skip execution check', default: false }), noInfo: Flags.boolean({ description: 'Skip printing the proposal info', default: false }), descriptionURL: Flags.string({ @@ -45,20 +51,29 @@ export default class Propose extends BaseCommand { } static examples = [ - 'propose --jsonTransactions ./transactions.json --deposit 10000 --from 0x5409ed021d9299bf6814279a6a1411a7e866a631 --descriptionURL https://gist.github.com/yorhodes/46430eacb8ed2f73f7bf79bef9d58a33', + 'propose --jsonTransactions ./transactions.json --deposit 10000e18 --from 0x5409ed021d9299bf6814279a6a1411a7e866a631 --descriptionURL https://gist.github.com/yorhodes/46430eacb8ed2f73f7bf79bef9d58a33', + 'propose --jsonTransactions ./transactions.json --deposit 10000e18 --from 0x5409ed021d9299bf6814279a6a1411a7e866a631 --useMultiSig --for 0x6c3dDFB1A9e73B5F49eDD46624F4954Bf66CAe93 --descriptionURL https://gist.github.com/yorhodes/46430eacb8ed2f73f7bf79bef9d58a33', ] async run() { const kit = await this.getKit() const res = await this.parse(Propose) const account = res.flags.from + kit.defaultAccount = account const deposit = new BigNumber(res.flags.deposit) - kit.defaultAccount = account as StrongAddress - - await newCheckBuilder(this, account) - .hasEnoughCelo(account, deposit) - .exceedsProposalMinDeposit(deposit) - .runChecks() + if (res.flags.useMultiSig && !res.flags.for) { + this.error( + 'If the --useMultiSig flag is set, then the --for flag has to also be set to a Multisig address.' + ) + } + const useMultiSig = res.flags.useMultiSig + if (res.flags.for && !res.flags.useMultiSig) { + this.error('If the --for flag is set, then the --useMultiSig flag has to also be set.') + } + const proposerMultiSig = res.flags.for + ? await kit.contracts.getMultiSig(res.flags.for) + : undefined + const proposer = useMultiSig ? proposerMultiSig!.address : account const builder = new ProposalBuilder(kit) @@ -85,6 +100,14 @@ export default class Propose extends BaseCommand { const governance = await kit.contracts.getGovernance() + await newCheckBuilder(this, proposer) + .hasEnoughCelo(proposer, deposit) + .exceedsProposalMinDeposit(deposit) + .addConditionalCheck(`${account} is multisig signatory`, useMultiSig, () => + proposerMultiSig!.isOwner(account) + ) + .runChecks() + if (!res.flags.force) { const ok = await checkProposal(proposal, kit) if (!ok) { @@ -92,11 +115,22 @@ export default class Propose extends BaseCommand { } } - await displaySendTx( - 'proposeTx', - governance.propose(proposal, res.flags.descriptionURL), - { value: deposit.toFixed() }, - 'ProposalQueued' - ) + const governanceTx = governance.propose(proposal, res.flags.descriptionURL) + + if (useMultiSig) { + const multiSigTx = await proposerMultiSig!.submitOrConfirmTransaction( + governance.address, + governanceTx.txo, + deposit.toFixed() + ) + await displaySendTx('proposeTx', multiSigTx, {}, 'ProposalQueued') + } else { + await displaySendTx( + 'proposeTx', + governanceTx, + { value: deposit.toFixed() }, + 'ProposalQueued' + ) + } } } diff --git a/packages/cli/src/commands/reserve/transfergold.ts b/packages/cli/src/commands/reserve/transfergold.ts index 4b3bdd965..c081a0e28 100644 --- a/packages/cli/src/commands/reserve/transfergold.ts +++ b/packages/cli/src/commands/reserve/transfergold.ts @@ -43,7 +43,7 @@ export default class TransferGold extends BaseCommand { .addCheck(`${spender} is a reserve spender`, async () => reserve.isSpender(spender)) .addConditionalCheck(`${account} is a multisig signatory`, useMultiSig, async () => reserveSpenderMultiSig !== undefined - ? reserveSpenderMultiSig.isowner(account) + ? reserveSpenderMultiSig.isOwner(account) : new Promise(() => false) ) .addCheck(`${to} is another reserve address`, async () => reserve.isOtherReserveAddress(to)) diff --git a/packages/cli/src/test-utils/constants.ts b/packages/cli/src/test-utils/constants.ts new file mode 100644 index 000000000..65986889c --- /dev/null +++ b/packages/cli/src/test-utils/constants.ts @@ -0,0 +1,4 @@ +export const proxyBytecode = + '0x608060405234801561001057600080fd5b506100203361002560201b60201c565b610155565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156100c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a25050565b610a22806101646000396000f3fe60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea265627a7a72315820ddaaedbcde72a50c209acc3d9132e085934b56b89e72a05cc3c769d6941d429064736f6c634300050d0032' +export const multiSigBytecode = + '0x608060405234801561001057600080fd5b506139f3806100206000396000f3fe6080604052600436106101665760003560e01c80639ace38c2116100d1578063ba51a6df1161008a578063d74f8edd11610064578063d74f8edd14610a2e578063dc8452cd14610a59578063e20056e614610a84578063ee22610b14610af557610166565b8063ba51a6df146108f4578063c01a8c841461092f578063c64274741461096a57610166565b80639ace38c2146105f7578063a0e67e2b146106f0578063a24efcdf1461075c578063a8abe69a14610787578063b5dc40c314610839578063b77bf600146108c957610166565b80633411c81c116101235780633411c81c1461039a578063547415251461040d5780635eae79591461046a5780637065cb4814610504578063784547a7146105555780638b51d13f146105a857610166565b8063025e7c27146101c0578063158ef93e1461023b578063173825d91461026a57806320ea8d86146102bb5780632e6c3721146102f65780632f54bf6e14610331575b60003411156101be573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b3480156101cc57600080fd5b506101f9600480360360208110156101e357600080fd5b8101908080359060200190929190505050610b30565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561024757600080fd5b50610250610b6c565b604051808215151515815260200191505060405180910390f35b34801561027657600080fd5b506102b96004803603602081101561028d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b7e565b005b3480156102c757600080fd5b506102f4600480360360208110156102de57600080fd5b8101908080359060200190929190505050610f1b565b005b34801561030257600080fd5b5061032f6004803603602081101561031957600080fd5b81019080803590602001909291905050506111dc565b005b34801561033d57600080fd5b506103806004803603602081101561035457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611347565b604051808215151515815260200191505060405180910390f35b3480156103a657600080fd5b506103f3600480360360408110156103bd57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611367565b604051808215151515815260200191505060405180910390f35b34801561041957600080fd5b506104546004803603604081101561043057600080fd5b81019080803515159060200190929190803515159060200190929190505050611396565b6040518082815260200191505060405180910390f35b34801561047657600080fd5b506105026004803603606081101561048d57600080fd5b81019080803590602001906401000000008111156104aa57600080fd5b8201836020820111156104bc57600080fd5b803590602001918460208302840111640100000000831117156104de57600080fd5b90919293919293908035906020019092919080359060200190929190505050611448565b005b34801561051057600080fd5b506105536004803603602081101561052757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061182b565b005b34801561056157600080fd5b5061058e6004803603602081101561057857600080fd5b8101908080359060200190929190505050611bd5565b604051808215151515815260200191505060405180910390f35b3480156105b457600080fd5b506105e1600480360360208110156105cb57600080fd5b8101908080359060200190929190505050611d66565b6040518082815260200191505060405180910390f35b34801561060357600080fd5b506106306004803603602081101561061a57600080fd5b8101908080359060200190929190505050611e4d565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156106b2578082015181840152602081019050610697565b50505050905090810190601f1680156106df5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b3480156106fc57600080fd5b50610705611f42565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561074857808201518184015260208101905061072d565b505050509050019250505060405180910390f35b34801561076857600080fd5b50610771611fd0565b6040518082815260200191505060405180910390f35b34801561079357600080fd5b506107e2600480360360808110156107aa57600080fd5b810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611fd6565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561082557808201518184015260208101905061080a565b505050509050019250505060405180910390f35b34801561084557600080fd5b506108726004803603602081101561085c57600080fd5b8101908080359060200190929190505050612188565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156108b557808201518184015260208101905061089a565b505050509050019250505060405180910390f35b3480156108d557600080fd5b506108de6123e0565b6040518082815260200191505060405180910390f35b34801561090057600080fd5b5061092d6004803603602081101561091757600080fd5b81019080803590602001909291905050506123e6565b005b34801561093b57600080fd5b506109686004803603602081101561095257600080fd5b8101908080359060200190929190505050612551565b005b34801561097657600080fd5b50610a186004803603606081101561098d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109d457600080fd5b8201836020820111156109e657600080fd5b80359060200191846001830284011164010000000083111715610a0857600080fd5b909192939192939050505061286d565b6040518082815260200191505060405180910390f35b348015610a3a57600080fd5b50610a436128d1565b6040518082815260200191505060405180910390f35b348015610a6557600080fd5b50610a6e6128d6565b6040518082815260200191505060405180910390f35b348015610a9057600080fd5b50610af360048036036040811015610aa757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506128dc565b005b348015610b0157600080fd5b50610b2e60048036036020811015610b1857600080fd5b8101908080359060200190929190505050612db7565b005b60048181548110610b3d57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900460ff1681565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139716022913960400191505060405180910390fd5b80600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610cc2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060008090505b610d3960016004805490506131ec90919063ffffffff16565b811015610e70578273ffffffffffffffffffffffffffffffffffffffff1660048281548110610d6457fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610e55576004610dc660016004805490506131ec90919063ffffffff16565b81548110610dd057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660048281548110610e0857fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610e70565b610e6960018261323690919063ffffffff16565b9050610d20565b50610e8a60016004805490506131ec90919063ffffffff16565b600481610e97919061376a565b506004805490506005541115610eb657610eb56004805490506123e6565b5b6004805490506006541115610ed457610ed36004805490506111dc565b5b8173ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a25050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610fdb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611090576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061394a6027913960400191505060405180910390fd5b836001600082815260200190815260200160002060030160009054906101000a900460ff1615611128576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f7472616e73616374696f6e2077617320657865637574656420616c726561647981525060200191505060405180910390fd5b60006002600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611260576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139716022913960400191505060405180910390fd5b60048054905081603282111580156112785750818111155b8015611285575060008114155b8015611292575060008214155b611304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b826006819055507fa07eff79ea50418b0e96ff7c01d65eb6c3a5a240ee91cd81c70c89503dd41239836040518082815260200191505060405180910390a1505050565b60036020528060005260406000206000915054906101000a900460ff1681565b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600754811015611441578380156113d657506001600082815260200190815260200160002060030160009054906101000a900460ff16155b8061140a575082801561140957506001600082815260200190815260200160002060030160009054906101000a900460ff165b5b156114265761142360018361323690919063ffffffff16565b91505b61143a60018261323690919063ffffffff16565b905061139e565b5092915050565b6000809054906101000a900460ff16156114ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b60016000806101000a81548160ff0219169083151502179055508383905082603282111580156114fa5750818111155b8015611507575060008114155b8015611514575060008214155b611586576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b85859050836032821115801561159c5750818111155b80156115a9575060008114155b80156115b6575060008214155b611628576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b60008090505b8888905081101561180057600360008a8a8481811061164957fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161580156117105750600073ffffffffffffffffffffffffffffffffffffffff168989838181106116da57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b611765576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180613993602c913960400191505060405180910390fd5b6001600360008b8b8581811061177757fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506117f960018261323690919063ffffffff16565b905061162e565b50878760049190611812929190613796565b5085600581905550846006819055505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139716022913960400191505060405180910390fd5b80600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611970576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f6f776e657220616c72656164792065786973746564000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a14576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b611a2d600160048054905061323690919063ffffffff16565b60065460328211158015611a415750818111155b8015611a4e575060008114155b8015611a5b575060008214155b611acd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b6001600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060048590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000905060008090505b600480549050811015611d5a5760026000858152602001908152602001600020600060048381548110611c1157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611ca057611c9d60018361323690919063ffffffff16565b91505b60003073ffffffffffffffffffffffffffffffffffffffff166001600087815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050808015611d17575060065483145b80611d2d575080158015611d2c575060055483145b5b15611d3e5760019350505050611d61565b50611d5360018261323690919063ffffffff16565b9050611be2565b5060009150505b919050565b600080600090505b600480549050811015611e475760026000848152602001908152602001600020600060048381548110611d9d57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611e2c57611e2960018361323690919063ffffffff16565b91505b611e4060018261323690919063ffffffff16565b9050611d6e565b50919050565b60016020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611f255780601f10611efa57610100808354040283529160200191611f25565b820191906000526020600020905b815481529060010190602001808311611f0857829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b60606004805480602002602001604051908101604052809291908181526020018280548015611fc657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611f7c575b5050505050905090565b60065481565b60608060075460405190808252806020026020018201604052801561200a5781602001602082028038833980820191505090505b509050600080905060008090505b6007548110156120d45785801561205057506001600082815260200190815260200160002060030160009054906101000a900460ff16155b80612084575084801561208357506001600082815260200190815260200160002060030160009054906101000a900460ff165b5b156120b9578083838151811061209657fe5b6020026020010181815250506120b660018361323690919063ffffffff16565b91505b6120cd60018261323690919063ffffffff16565b9050612018565b6120e788886131ec90919063ffffffff16565b6040519080825280602002602001820160405280156121155781602001602082028038833980820191505090505b5093508790505b8681101561217d5782818151811061213057fe5b60200260200101518461214c8a846131ec90919063ffffffff16565b8151811061215657fe5b60200260200101818152505061217660018261323690919063ffffffff16565b905061211c565b505050949350505050565b6060806004805490506040519080825280602002602001820160405280156121bf5781602001602082028038833980820191505090505b509050600080905060008090505b60048054905081101561232457600260008681526020019081526020016000206000600483815481106121fc57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612309576004818154811061228157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383815181106122b857fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061230660018361323690919063ffffffff16565b91505b61231d60018261323690919063ffffffff16565b90506121cd565b816040519080825280602002602001820160405280156123535781602001602082028038833980820191505090505b509350600090505b818110156123d85782818151811061236f57fe5b602002602001015184828151811061238357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506123d160018261323690919063ffffffff16565b905061235b565b505050919050565b60075481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461246a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139716022913960400191505060405180910390fd5b60048054905081603282111580156124825750818111155b801561248f575060008114155b801561249c575060008214155b61250e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b826005819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612611576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156126eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f7472616e73616374696f6e20646f6573206e6f7420657869737400000000000081525060200191505060405180910390fd5b82336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156127a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061391f602b913960400191505060405180910390fd5b60016002600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361285785611bd5565b156128665761286585612db7565b5b5050505050565b60006128be858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506132be565b90506128c981612551565b949350505050565b603281565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139716022913960400191505060405180910390fd5b81600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612ac4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b82600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612b85576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f6f776e657220616c72656164792065786973746564000000000000000000000081525060200191505060405180910390fd5b60008090505b600480549050811015612c79578573ffffffffffffffffffffffffffffffffffffffff1660048281548110612bbc57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612c5e578460048281548110612c1157fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612c79565b612c7260018261323690919063ffffffff16565b9050612b8b565b506000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612e77576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612f2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061394a6027913960400191505060405180910390fd5b836001600082815260200190815260200160002060030160009054906101000a900460ff1615612fc4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f7472616e73616374696f6e2077617320657865637574656420616c726561647981525060200191505060405180910390fd5b612fcd85611bd5565b61303f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f5472616e73616374696f6e206e6f7420636f6e6669726d65642e00000000000081525060200191505060405180910390fd5b600060016000878152602001908152602001600020905060018160030160006101000a81548160ff02191690831515021790555060606131448260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168360010154846002018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561313a5780601f1061310f5761010080835404028352916020019161313a565b820191906000526020600020905b81548152906001019060200180831161311d57829003601f168201915b5050505050613498565b9050867f0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f826040518080602001828103825283818151815260200191508051906020019080838360005b838110156131a957808201518184015260208101905061318e565b50505050905090810190601f1680156131d65780820380516001836020036101000a031916815260200191505b509250505060405180910390a250505050505050565b600061322e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061365f565b905092915050565b6000808284019050838110156132b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600083600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613364576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b600754915060405180608001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001600015158152506001600084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101556040820151816002019080519060200190613423929190613836565b5060608201518160030160006101000a81548160ff02191690831515021790555090505061345d600160075461323690919063ffffffff16565b600781905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6060600082511115613520576134ad8461371f565b61351f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b600060608573ffffffffffffffffffffffffffffffffffffffff1685856040518082805190602001908083835b60208310613570578051825260208201915060208101905060208303925061354d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146135d2576040519150601f19603f3d011682016040523d82523d6000602084013e6135d7565b606091505b50809250819350505081613653576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5472616e73616374696f6e20657865637574696f6e206661696c65642e00000081525060200191505060405180910390fd5b80925050509392505050565b600083831115829061370c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156136d15780820151818401526020810190506136b6565b50505050905090810190601f1680156136fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561376157506000801b8214155b92505050919050565b8154818355818111156137915781836000526020600020918201910161379091906138b6565b5b505050565b828054828255906000526020600020908101928215613825579160200282015b8281111561382457823573ffffffffffffffffffffffffffffffffffffffff168260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906137b6565b5b50905061383291906138db565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061387757805160ff19168380011785556138a5565b828001600101855582156138a5579182015b828111156138a4578251825591602001919060010190613889565b5b5090506138b291906138b6565b5090565b6138d891905b808211156138d45760008160009055506001016138bc565b5090565b90565b61391b91905b8082111561391757600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016138e1565b5090565b9056fe7472616e73616374696f6e2077617320616c726561647920636f6e6669726d656420666f72206f776e65727472616e73616374696f6e20776173206e6f7420636f6e6669726d656420666f72206f776e65726d73672e73656e64657220776173206e6f74206d756c74697369672077616c6c65746f776e657220776173206e756c6c206f7220616c726561647920676976656e206f776e657220737461747573a265627a7a7231582048e9e033be9fab18105a8fd3cc78442bca466a52949036d1e14f806a4205ff6864736f6c634300050d0032' diff --git a/packages/cli/src/test-utils/multisigUtils.ts b/packages/cli/src/test-utils/multisigUtils.ts new file mode 100644 index 000000000..1295b0f6c --- /dev/null +++ b/packages/cli/src/test-utils/multisigUtils.ts @@ -0,0 +1,56 @@ +import { multiSigABI, proxyABI } from '@celo/abis' +import { StrongAddress } from '@celo/base' +import { ContractKit } from '@celo/contractkit' +import { multiSigBytecode, proxyBytecode } from './constants' + +export async function createMultisig( + kit: ContractKit, + owners: StrongAddress[], + requiredSignatures: number, + requiredInternalSignatures: number +): Promise { + const accounts = (await kit.web3.eth.getAccounts()) as StrongAddress[] + kit.defaultAccount = accounts[0] + + // Deploy Proxy contract + const proxyDeploymentTx = await kit.sendTransaction({ + data: proxyBytecode, + }) + const { contractAddress: proxyAddress } = await proxyDeploymentTx.waitReceipt() + // Deploy MultiSig contract + const multisigDeploymentTx = await kit.sendTransaction({ + data: multiSigBytecode, + }) + const { contractAddress: multiSigAddress } = await multisigDeploymentTx.waitReceipt() + + // Configure and initialize MultiSig + const initializerAbi = multiSigABI.find( + (abi) => abi.type === 'function' && abi.name === 'initialize' + ) + const proxy = new kit.web3.eth.Contract(proxyABI as any, proxyAddress) + const baseFee = await kit.web3.eth.getBlock('latest').then((block: any) => block.baseFeePerGas) + const priorityFee = kit.web3.utils.toWei('2', 'gwei') + const initMethod = proxy.methods._setAndInitializeImplementation + const callData = kit.web3.eth.abi.encodeFunctionCall(initializerAbi as any, [ + owners as any, + requiredSignatures as any, + requiredInternalSignatures as any, + ]) + const initTx = initMethod(multiSigAddress, callData) + await initTx.send({ + from: kit.defaultAccount, + gas: await initTx.estimateGas({ from: kit.defaultAccount }), + maxPriorityFeePerGas: priorityFee, + maxFeePerGas: (BigInt(baseFee) + BigInt(priorityFee)).toString(), + }) + const transferOwnershipMethod = proxy.methods._transferOwnership + const changeOwnerTx = transferOwnershipMethod(proxyAddress) + await changeOwnerTx.send({ + from: kit.defaultAccount, + gas: await changeOwnerTx.estimateGas({ from: kit.defaultAccount }), + maxPriorityFeePerGas: priorityFee, + maxFeePerGas: (BigInt(baseFee) + BigInt(priorityFee)).toString(), + }) + + return proxyAddress as StrongAddress +} diff --git a/packages/cli/src/utils/off-chain-data.ts b/packages/cli/src/utils/off-chain-data.ts index 8242fc911..1a14b64e8 100644 --- a/packages/cli/src/utils/off-chain-data.ts +++ b/packages/cli/src/utils/off-chain-data.ts @@ -58,3 +58,6 @@ export abstract class OffchainDataCommand extends BaseCommand { : new LocalStorageWriter(directory) } } + +export const DEPRECATION_NOTICE = + 'offchain-read and offchain-write commands are deprecated as CIP8 was abandonded. They will be removed next major release.' diff --git a/packages/docs/sdk/docs/connect/modules.md b/packages/docs/sdk/docs/connect/modules.md index fe335cce8..9d60f3dc9 100644 --- a/packages/docs/sdk/docs/connect/modules.md +++ b/packages/docs/sdk/docs/connect/modules.md @@ -14,6 +14,7 @@ - [utils/abi-utils](modules/utils_abi_utils.md) - [utils/celo-transaction-object](modules/utils_celo_transaction_object.md) - [utils/formatter](modules/utils_formatter.md) +- [utils/is-cel2](modules/utils_is_cel2.md) - [utils/provider-utils](modules/utils_provider_utils.md) - [utils/rpc-caller](modules/utils_rpc_caller.md) - [utils/tx-params-normalizer](modules/utils_tx_params_normalizer.md) diff --git a/packages/docs/sdk/docs/connect/modules/index.md b/packages/docs/sdk/docs/connect/modules/index.md index 2fd441869..5339b7626 100644 --- a/packages/docs/sdk/docs/connect/modules/index.md +++ b/packages/docs/sdk/docs/connect/modules/index.md @@ -41,6 +41,7 @@ - [JsonRpcPayload](index.md#jsonrpcpayload) - [JsonRpcResponse](index.md#jsonrpcresponse) - [LegacyTXProperties](index.md#legacytxproperties) +- [PROXY\_ADMIN\_ADDRESS](index.md#proxy_admin_address) - [Provider](index.md#provider) - [RLPEncodedTx](index.md#rlpencodedtx) - [ReadOnlyWallet](index.md#readonlywallet) @@ -51,6 +52,7 @@ - [decodeStringParameter](index.md#decodestringparameter) - [getAbiByName](index.md#getabibyname) - [getRandomId](index.md#getrandomid) +- [isCel2](index.md#iscel2) - [isPresent](index.md#ispresent) - [parseDecodedParams](index.md#parsedecodedparams) - [rpcCallHandler](index.md#rpccallhandler) @@ -290,6 +292,12 @@ Re-exports [LegacyTXProperties](../interfaces/types.LegacyTXProperties.md) ___ +### PROXY\_ADMIN\_ADDRESS + +Re-exports [PROXY_ADMIN_ADDRESS](utils_is_cel2.md#proxy_admin_address) + +___ + ### Provider Re-exports [Provider](../interfaces/types.Provider.md) @@ -350,6 +358,12 @@ Re-exports [getRandomId](utils_rpc_caller.md#getrandomid) ___ +### isCel2 + +Re-exports [isCel2](utils_is_cel2.md#iscel2) + +___ + ### isPresent Re-exports [isPresent](connection.md#ispresent) diff --git a/packages/docs/sdk/docs/connect/modules/utils_is_cel2.md b/packages/docs/sdk/docs/connect/modules/utils_is_cel2.md new file mode 100644 index 000000000..e09c901b1 --- /dev/null +++ b/packages/docs/sdk/docs/connect/modules/utils_is_cel2.md @@ -0,0 +1,43 @@ +[@celo/connect](../README.md) / [Exports](../modules.md) / utils/is-cel2 + +# Module: utils/is-cel2 + +## Table of contents + +### Variables + +- [PROXY\_ADMIN\_ADDRESS](utils_is_cel2.md#proxy_admin_address) + +### Functions + +- [isCel2](utils_is_cel2.md#iscel2) + +## Variables + +### PROXY\_ADMIN\_ADDRESS + +• `Const` **PROXY\_ADMIN\_ADDRESS**: ``"0x4200000000000000000000000000000000000018"`` + +#### Defined in + +[packages/sdk/connect/src/utils/is-cel2.ts:8](https://github.com/celo-org/developer-tooling/blob/master/packages/sdk/connect/src/utils/is-cel2.ts#L8) + +## Functions + +### isCel2 + +▸ **isCel2**(`web3`): `Promise`\<`boolean`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `web3` | `default` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Defined in + +[packages/sdk/connect/src/utils/is-cel2.ts:10](https://github.com/celo-org/developer-tooling/blob/master/packages/sdk/connect/src/utils/is-cel2.ts#L10) diff --git a/packages/docs/sdk/docs/contractkit/classes/wrappers_MultiSig.MultiSigWrapper.md b/packages/docs/sdk/docs/contractkit/classes/wrappers_MultiSig.MultiSigWrapper.md index d9883b7b5..d10e56b5f 100644 --- a/packages/docs/sdk/docs/contractkit/classes/wrappers_MultiSig.MultiSigWrapper.md +++ b/packages/docs/sdk/docs/contractkit/classes/wrappers_MultiSig.MultiSigWrapper.md @@ -26,7 +26,7 @@ Contract for handling multisig actions - [getOwners](wrappers_MultiSig.MultiSigWrapper.md#getowners) - [getRequired](wrappers_MultiSig.MultiSigWrapper.md#getrequired) - [getTransactionCount](wrappers_MultiSig.MultiSigWrapper.md#gettransactioncount) -- [isowner](wrappers_MultiSig.MultiSigWrapper.md#isowner) +- [isOwner](wrappers_MultiSig.MultiSigWrapper.md#isowner) - [methodIds](wrappers_MultiSig.MultiSigWrapper.md#methodids) - [replaceOwner](wrappers_MultiSig.MultiSigWrapper.md#replaceowner) - [totalTransactionCount](wrappers_MultiSig.MultiSigWrapper.md#totaltransactioncount) @@ -212,9 +212,9 @@ ___ ___ -### isowner +### isOwner -• **isowner**: (`owner`: `string`) => `Promise`\<`boolean`\> +• **isOwner**: (`owner`: `string`) => `Promise`\<`boolean`\> #### Type declaration diff --git a/packages/docs/sdk/requirements.txt b/packages/docs/sdk/requirements.txt index c77d23ea2..996c59a7a 100644 --- a/packages/docs/sdk/requirements.txt +++ b/packages/docs/sdk/requirements.txt @@ -1 +1 @@ -jinja2==3.1.3 +jinja2==3.1.4 diff --git a/packages/sdk/connect/src/index.ts b/packages/sdk/connect/src/index.ts index d294dc867..e94689063 100644 --- a/packages/sdk/connect/src/index.ts +++ b/packages/sdk/connect/src/index.ts @@ -3,6 +3,7 @@ export * from './connection' export * from './types' export * from './utils/abi-utils' export * from './utils/celo-transaction-object' +export * from './utils/is-cel2' export * from './utils/rpc-caller' export * from './utils/tx-result' export * from './wallet' diff --git a/packages/sdk/connect/src/utils/is-cel2.test.ts b/packages/sdk/connect/src/utils/is-cel2.test.ts new file mode 100644 index 000000000..2ed6c0a06 --- /dev/null +++ b/packages/sdk/connect/src/utils/is-cel2.test.ts @@ -0,0 +1,46 @@ +import Web3 from 'web3' +import { PROXY_ADMIN_ADDRESS, isCel2 } from './is-cel2' + +describe('isCel2', () => { + it('recognizes cel2', async () => { + const getCodeMock = jest.fn() + const web3Mock = { + eth: { + getCode: getCodeMock, + }, + } + + getCodeMock.mockReturnValue('0xbytecode') + + expect(await isCel2(web3Mock as unknown as Web3)).toBe(true) + expect(getCodeMock).toHaveBeenCalledWith(PROXY_ADMIN_ADDRESS) + }) + + it('does not recognize cel2 when 0x returned', async () => { + const getCodeMock = jest.fn() + const web3Mock = { + eth: { + getCode: getCodeMock, + }, + } + + getCodeMock.mockReturnValue('0x') + + expect(await isCel2(web3Mock as unknown as Web3)).toBe(false) + expect(getCodeMock).toHaveBeenCalledWith(PROXY_ADMIN_ADDRESS) + }) + + it('does not recognize cel2 when not 0x returned', async () => { + const getCodeMock = jest.fn() + const web3Mock = { + eth: { + getCode: getCodeMock, + }, + } + + getCodeMock.mockReturnValue(undefined) + + expect(await isCel2(web3Mock as unknown as Web3)).toBe(false) + expect(getCodeMock).toHaveBeenCalledWith(PROXY_ADMIN_ADDRESS) + }) +}) diff --git a/packages/sdk/connect/src/utils/is-cel2.ts b/packages/sdk/connect/src/utils/is-cel2.ts new file mode 100644 index 000000000..878fccf90 --- /dev/null +++ b/packages/sdk/connect/src/utils/is-cel2.ts @@ -0,0 +1,18 @@ +import Web3 from 'web3' + +/* + * This util checks if we're in L2 context, it's a port of the technique used in + * https://github.com/celo-org/celo-monorepo/blob/da9b4955c1fdc8631980dc4adf9b05e0524fc228/packages/protocol/contracts-0.8/common/IsL2Check.sol#L17 + */ + +export const PROXY_ADMIN_ADDRESS = '0x4200000000000000000000000000000000000018' + +export const isCel2 = async (web3: Web3) => { + const code = await web3.eth.getCode(PROXY_ADMIN_ADDRESS) + + if (typeof code === 'string') { + return code != '0x' && code.length > 2 + } + + return false +} diff --git a/packages/sdk/contractkit/src/wrappers/MultiSig.ts b/packages/sdk/contractkit/src/wrappers/MultiSig.ts index d009a91bb..d27c146af 100644 --- a/packages/sdk/contractkit/src/wrappers/MultiSig.ts +++ b/packages/sdk/contractkit/src/wrappers/MultiSig.ts @@ -67,7 +67,7 @@ export class MultiSigWrapper extends BaseWrapper { ) } - isowner: (owner: Address) => Promise = proxyCall(this.contract.methods.isOwner) + isOwner: (owner: Address) => Promise = proxyCall(this.contract.methods.isOwner) getOwners = proxyCall(this.contract.methods.getOwners) getRequired = proxyCall(this.contract.methods.required, undefined, valueToBigNumber) getInternalRequired = proxyCall(