From 0c7dc30a504658631ac2a1ad3d9a0f5bfe2af6d8 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Sat, 24 Aug 2024 11:49:44 +0100 Subject: [PATCH] feat: add deployer service --- .gitignore | 4 +- .prettierignore | 3 +- packages/contracts/ts/index.ts | 2 + packages/coordinator/.env.example | 12 +- .../default-deployed-contracts.json | 1554 +++++++++++++++++ packages/coordinator/tests/e2e.aa.test.ts | 121 +- packages/coordinator/ts/app.module.ts | 2 + .../ts/common/__tests__/common.test.ts | 118 +- .../ts/common/accountAbstraction.ts | 93 +- packages/coordinator/ts/common/errors.ts | 22 +- packages/coordinator/ts/common/index.ts | 1 + packages/coordinator/ts/common/networks.ts | 4 +- .../__tests__/deployer.controller.test.ts | 96 + .../__tests__/deployer.service.test.ts | 526 ++++++ .../ts/deployer/__tests__/utils.ts | 45 + packages/coordinator/ts/deployer/constants.ts | 14 + .../ts/deployer/deployer.controller.ts | 62 + .../ts/deployer/deployer.module.ts | 15 + .../ts/deployer/deployer.service.ts | 936 ++++++++++ packages/coordinator/ts/deployer/dto.ts | 100 ++ packages/coordinator/ts/deployer/types.ts | 263 +++ packages/coordinator/ts/deployer/utils.ts | 10 + .../__tests__/sessionKeys.service.test.ts | 1 + .../ts/sessionKeys/sessionKeys.service.ts | 4 +- packages/coordinator/ts/sessionKeys/types.ts | 12 +- packages/interface/package.json | 8 +- pnpm-lock.yaml | 243 ++- 27 files changed, 4137 insertions(+), 134 deletions(-) create mode 100644 packages/coordinator/default-deployed-contracts.json create mode 100644 packages/coordinator/ts/deployer/__tests__/deployer.controller.test.ts create mode 100644 packages/coordinator/ts/deployer/__tests__/deployer.service.test.ts create mode 100644 packages/coordinator/ts/deployer/__tests__/utils.ts create mode 100644 packages/coordinator/ts/deployer/constants.ts create mode 100644 packages/coordinator/ts/deployer/deployer.controller.ts create mode 100644 packages/coordinator/ts/deployer/deployer.module.ts create mode 100644 packages/coordinator/ts/deployer/deployer.service.ts create mode 100644 packages/coordinator/ts/deployer/dto.ts create mode 100644 packages/coordinator/ts/deployer/types.ts create mode 100644 packages/coordinator/ts/deployer/utils.ts diff --git a/.gitignore b/.gitignore index 6f4ab1f2..e9cd3f3e 100644 --- a/.gitignore +++ b/.gitignore @@ -32,8 +32,8 @@ yarn-error.log* # do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables .env .env*.local -deploy-config.json -deployed-contracts.json +packages/coordinator/deploy-config.json +packages/coordinator/deployed-contracts.json # vercel .vercel diff --git a/.prettierignore b/.prettierignore index 7d07a7f6..6cd83202 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,4 +17,5 @@ test-results/ packages/subgraph/templates/subgraph.template.yaml packages/subgraph/subgraph.yaml packages/subgraph/generated/ - +packages/contracts/deploy-config.json +packages/contracts/deployed-contracts.json diff --git a/packages/contracts/ts/index.ts b/packages/contracts/ts/index.ts index 98027a6c..5c74968e 100644 --- a/packages/contracts/ts/index.ts +++ b/packages/contracts/ts/index.ts @@ -1 +1,3 @@ export { ERegistryManagerRequestType, ERegistryManagerRequestStatus } from "./constants"; + +export * from "../typechain-types"; diff --git a/packages/coordinator/.env.example b/packages/coordinator/.env.example index 027629d7..ecfc066a 100644 --- a/packages/coordinator/.env.example +++ b/packages/coordinator/.env.example @@ -48,8 +48,14 @@ SUBGRAPH_FOLDER=./node_modules/maci-subgraph # API Key for Pimlico RPC Bundler PIMLICO_API_KEY="pim_" -# A private key for e2e tests -TEST_PRIVATE_KEY="" +# RPC URL for Zerodev bundler on OP sepolia +ZERODEV_BUNDLER_RPC_OP_SEPOLIA="" + +# RPC URL for Zerodev bundler on OP mainnet +ZERODEV_BUNDLER_RPC_OP="" -# An RPC API KEY to interact with live networks (used in e2e tests) +# RPC API KEY for Alchemy RPC_API_KEY="" + +# A private key for e2e tests +TEST_PRIVATE_KEY="" diff --git a/packages/coordinator/default-deployed-contracts.json b/packages/coordinator/default-deployed-contracts.json new file mode 100644 index 00000000..5caca84d --- /dev/null +++ b/packages/coordinator/default-deployed-contracts.json @@ -0,0 +1,1554 @@ +{ + "optimism-sepolia": { + "instance": { + "0x4473aC3e68ad78D67757336ABaAa2Dced08cfcdF": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x8b62e4abe0db623981b8873a5f88f3c447b4202159e5d47b1d3158c1914afb91", + "verify": { + "args": "[\"99\"]" + } + }, + "0xa4fF6765C207C84AbeFCe0226b24204f9ceBAB45": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x7fa84fe66edeb0f6d13999344289d0404eac443e52dab4c9b25d7415ff84e45b", + "verify": { + "args": "[]" + } + }, + "0xB1abb44291ff487f96636758b07Ccd9881f64c9A": { + "id": "Verifier", + "deploymentTxHash": "0x50377144a799369d26cb0f4de471a9c95a3b7de0a3aed18363cb1204ee45213a", + "verify": { + "args": "[]" + } + }, + "0x07490eba00dc4ACA6721D052Fa4C5002Aa077233": { + "id": "PoseidonT3", + "deploymentTxHash": "0x799a38ec8dfa740286f496da91d3549cfc923aa8f7c32cf0af2e03829ddb105f", + "verify": { + "args": "[]" + } + }, + "0xbb0e724CE02e5E7eDd31e632dc6e59F229a1126d": { + "id": "PoseidonT4", + "deploymentTxHash": "0x82e8dedbfd9a583b7b09d5e3d7a0b14d0b7a5062438ab70d3154d15f888ef960", + "verify": { + "args": "[]" + } + }, + "0xE0398F7DFAC494c530F6404AfEaC8669ABeD2679": { + "id": "PoseidonT5", + "deploymentTxHash": "0xd57d72b7d519b81bd80b01c0b80669fb4c14b3b349b3d5555e7007ec0adae68d", + "verify": { + "args": "[]" + } + }, + "0xfD77833F10a29c76A6a0ede235Eb651D744d0E2F": { + "id": "PoseidonT6", + "deploymentTxHash": "0xb37f2be891314378b5f8579ba5bd95df7b0f1652b4f91356ddeb9e86ea7311fe", + "verify": { + "args": "[]" + } + }, + "0xad844a9567ada5996FFC0D2DeC78b3767a1c0501": { + "id": "PollFactory", + "deploymentTxHash": "0x99a4dd853297e4aa9a824c509268926875f9ec2971b6c6e74b3179fd4f8845ca", + "verify": { + "args": "[]" + } + }, + "0xbBb6f1B4232F993e5a026217a3D596B332062CB3": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0xe817a6c240bdbb19a974f9a36eed9fd89794229496ed51db591b23382910bbb2", + "verify": { + "args": "[]" + } + }, + "0x1356f05179cdcAD2D8708B539A75de082118de92": { + "id": "TallyFactory", + "deploymentTxHash": "0x7b57994dccdbeeff25d9f7f58fde0f35cd10ce53eb160009c565033a370a0600", + "verify": { + "args": "[]" + } + }, + "0x42B1AB3d98B8235204E75112e5d9E974cE7531cC": { + "id": "VkRegistry", + "deploymentTxHash": "0x1b05a22de2735ed74b58532303e7af01659b066206e696f4c8e6df61bc97f442", + "verify": { + "args": "[]" + } + }, + "0x6f9F7Fef2FF7F5D1Ff8966F751EC154146d8f431": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0xe5b6ce84a95af89c64cff82901bc26b96d67bf4ffb18d4e82ebfcbc19c4392f2", + "verify": { + "args": "[\"99\"]" + } + }, + "0x6b414ff158581Ac940797463a44221d0ba6A0B9C": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x5f7640018acb7155aa510e05cca92ad40003327dfe75fcab7d61bd21fefdea67", + "verify": { + "args": "[]" + } + } + }, + "named": { + "Verifier": { + "address": "0xB1abb44291ff487f96636758b07Ccd9881f64c9A", + "count": 1 + }, + "PoseidonT3": { + "address": "0x07490eba00dc4ACA6721D052Fa4C5002Aa077233", + "count": 1 + }, + "PoseidonT4": { + "address": "0xbb0e724CE02e5E7eDd31e632dc6e59F229a1126d", + "count": 1 + }, + "PoseidonT5": { + "address": "0xE0398F7DFAC494c530F6404AfEaC8669ABeD2679", + "count": 1 + }, + "PoseidonT6": { + "address": "0xfD77833F10a29c76A6a0ede235Eb651D744d0E2F", + "count": 1 + }, + "PollFactory": { + "address": "0xad844a9567ada5996FFC0D2DeC78b3767a1c0501", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xbBb6f1B4232F993e5a026217a3D596B332062CB3", + "count": 1 + }, + "TallyFactory": { + "address": "0x1356f05179cdcAD2D8708B539A75de082118de92", + "count": 1 + }, + "VkRegistry": { + "address": "0x42B1AB3d98B8235204E75112e5d9E974cE7531cC", + "count": 1 + }, + "ConstantInitialVoiceCreditProxy": { + "address": "0x6f9F7Fef2FF7F5D1Ff8966F751EC154146d8f431", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x6b414ff158581Ac940797463a44221d0ba6A0B9C", + "count": 1 + } + } + }, + "arbitrum-sepolia": { + "instance": { + "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x897bfb740aba18fff51fcde7c5c1f97b2727f4a0122118fa300411684004211c", + "verify": { + "args": "[\"99\"]" + } + }, + "0x9e98cAA76492338627BAD0e5a6AA2762d827E169": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x5a740ad234560fab4097150f6c6acbf95224b4949ff3d82b477903a435a60621", + "verify": { + "args": "[]" + } + }, + "0xB400794f463d90ce5f462A43d8E6f9155656d02d": { + "id": "Verifier", + "deploymentTxHash": "0xbf743a2514c0a57bb7972a5a2cbaa2b57ffeac78c51ed730b5ccf29e2a428ad3", + "verify": { + "args": "[]" + } + }, + "0xa0e0aC07c211D329ebA2D6ec552F4dC1B230A89A": { + "id": "PoseidonT3", + "deploymentTxHash": "0x8c0f24d6d5837334143bf181ae74ae8c4d8218f40681146f88cc6d793b416065", + "verify": { + "args": "[]" + } + }, + "0x0CC8B7Aed7d79a8B948636242706265548D0B10a": { + "id": "PoseidonT4", + "deploymentTxHash": "0xbc566db1ae8192e94418cfc9082d2a8f7dc71352438b92790a8ae9e01de86999", + "verify": { + "args": "[]" + } + }, + "0x43B519FF023757508311518AC41B5fA1CfD57181": { + "id": "PoseidonT5", + "deploymentTxHash": "0x28c63a2021aac9f0400affd73d9bd57de107a557bed40299ab0ee7adb58fdcb1", + "verify": { + "args": "[]" + } + }, + "0xb123798B1b21082100D289BeA24bFF0F8dfcbEe1": { + "id": "PoseidonT6", + "deploymentTxHash": "0xdfa42ab39a49f75c8d14cd750610b1cf2aaecf6f767362f732551416ae4445c5", + "verify": { + "args": "[]" + } + }, + "0xBa350B0cF67a0dEDa103A5d0d297bd120bF87E39": { + "id": "PollFactory", + "deploymentTxHash": "0x4a955482e8a4ecb0e275cb978980b2b85c765c0ced4e9005612ac989a5769d11", + "verify": { + "args": "[]" + } + }, + "0x96FD5e4E40671Bf8d5f1d0E3F3402488680B8376": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x51727155edfd8c178c583801f24714dd9e4fbdd6e7c9bbbe0e7663ea3d9a3198", + "verify": { + "args": "[]" + } + }, + "0xEEBc671e15B3f1c7483161F866d76ad84645d7C8": { + "id": "TallyFactory", + "deploymentTxHash": "0xc1c7e05a40164b8429517eed34b2042e593df11091840a9820451ee0d8f796c9", + "verify": { + "args": "[]" + } + }, + "0xE21F9Ea298b62032B3C2206955cd12c4Ab0a046b": { + "id": "VkRegistry", + "deploymentTxHash": "0x2216dc97941a301e817d630a1a5ec31a7997f0d3ea5bcf5581defd374d8ab8aa", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x9e98cAA76492338627BAD0e5a6AA2762d827E169", + "count": 1 + }, + "Verifier": { + "address": "0xB400794f463d90ce5f462A43d8E6f9155656d02d", + "count": 1 + }, + "PoseidonT3": { + "address": "0xa0e0aC07c211D329ebA2D6ec552F4dC1B230A89A", + "count": 1 + }, + "PoseidonT4": { + "address": "0x0CC8B7Aed7d79a8B948636242706265548D0B10a", + "count": 1 + }, + "PoseidonT5": { + "address": "0x43B519FF023757508311518AC41B5fA1CfD57181", + "count": 1 + }, + "PoseidonT6": { + "address": "0xb123798B1b21082100D289BeA24bFF0F8dfcbEe1", + "count": 1 + }, + "PollFactory": { + "address": "0xBa350B0cF67a0dEDa103A5d0d297bd120bF87E39", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x96FD5e4E40671Bf8d5f1d0E3F3402488680B8376", + "count": 1 + }, + "TallyFactory": { + "address": "0xEEBc671e15B3f1c7483161F866d76ad84645d7C8", + "count": 1 + }, + "VkRegistry": { + "address": "0xE21F9Ea298b62032B3C2206955cd12c4Ab0a046b", + "count": 1 + } + } + }, + "base-sepolia": { + "instance": { + "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x2d94f77f843c7f3f19eec1d0cac75a1260e0708e47ee9cb7fbf72c63ebcb156b", + "verify": { + "args": "[\"99\"]" + } + }, + "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x24c07b7ccc8ab143f03b03749ad81e4830456d4353f3c9783ffd08b3ea2d1004", + "verify": { + "args": "[]" + } + }, + "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27": { + "id": "Verifier", + "deploymentTxHash": "0x536d8665489c174d17d584b9dc3e6a6ccc595e5b232f8029879ae49e2c38c3d6", + "verify": { + "args": "[]" + } + }, + "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4": { + "id": "PoseidonT3", + "deploymentTxHash": "0xc87ffe646d64cde4e819636490a8eb8d246233aeb58b42d06ff76ab04c07a301", + "verify": { + "args": "[]" + } + }, + "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6": { + "id": "PoseidonT4", + "deploymentTxHash": "0xcebcf39fd5857e595b50139004123c27a29c504ed12440c062833fcda2525848", + "verify": { + "args": "[]" + } + }, + "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968": { + "id": "PoseidonT5", + "deploymentTxHash": "0x64d9db02a0b4cb29135e56becafe30c045919f20328e3d10a50f69f27add94e9", + "verify": { + "args": "[]" + } + }, + "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E": { + "id": "PoseidonT6", + "deploymentTxHash": "0xfd556b278a7b10b70382207c733de3f9e97ad3e2ed6821a3acd16011f3b94084", + "verify": { + "args": "[]" + } + }, + "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607": { + "id": "PollFactory", + "deploymentTxHash": "0xe89d4e3c14bd680691568382e38b9400034632672b802eb1ae684afc03f7bf82", + "verify": { + "args": "[]" + } + }, + "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x7d709c06be1a8055a9f12dc40eb71b27ce71fccddf5ffb1f488ed5ed3cadfbd6", + "verify": { + "args": "[]" + } + }, + "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C": { + "id": "TallyFactory", + "deploymentTxHash": "0xb5e583c45a53ac522d1025a0b594f3e58dd4fa1f837baadeb47bcc164eac0439", + "verify": { + "args": "[]" + } + }, + "0x6aA5baD99aC44bB008930c68CE2249549Cf10944": { + "id": "VkRegistry", + "deploymentTxHash": "0xdb1cbc7acc63c814dc238177adbf4012a1ccf743be3b2ef8ac2bde66177fe3a1", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f", + "count": 1 + }, + "Verifier": { + "address": "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27", + "count": 1 + }, + "PoseidonT3": { + "address": "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4", + "count": 1 + }, + "PoseidonT4": { + "address": "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6", + "count": 1 + }, + "PoseidonT5": { + "address": "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968", + "count": 1 + }, + "PoseidonT6": { + "address": "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E", + "count": 1 + }, + "PollFactory": { + "address": "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5", + "count": 1 + }, + "TallyFactory": { + "address": "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C", + "count": 1 + }, + "VkRegistry": { + "address": "0x6aA5baD99aC44bB008930c68CE2249549Cf10944", + "count": 1 + } + } + }, + "scroll-sepolia": { + "instance": { + "0xB486cce9B4507A67Db147B0802D5673774C8D278": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x19fffe5a56c36405586b627d896513ca6949b654faac219e5d39041f7ce67d93", + "verify": { + "args": "[\"99\"]" + } + }, + "0x83dD551541C580e338206f1f677835D427C92dE2": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x637fbce4ecd191f31f768f3d46a67727c29e61149cd9d2f8830f2c685cda5019", + "verify": { + "args": "[]" + } + }, + "0xD5C41106db85EDd0298279AcFCE5A722060cc5f9": { + "id": "Verifier", + "deploymentTxHash": "0xeb106e6aa2ec41e7fd36306d843cdc2a70e6b2ed3e2156664177a23db29bf400", + "verify": { + "args": "[]" + } + }, + "0x88C2c6A7535463962A34757FE63cc4F296381aba": { + "id": "PoseidonT3", + "deploymentTxHash": "0xe6f4d9bcbd8012fd7bf90aefe60818722cbeef7c40dff937aa4fb90c06e2384a", + "verify": { + "args": "[]" + } + }, + "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66": { + "id": "PoseidonT4", + "deploymentTxHash": "0x041f2bfa9258dde9a411d9bf6155bdb9282dbd4eb4182cc9052e6285679c0ff1", + "verify": { + "args": "[]" + } + }, + "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274": { + "id": "PoseidonT5", + "deploymentTxHash": "0x197041bb741918efd7d1cb1ccdd58a76e53da56fdebfa7fa3f5850349cb457d6", + "verify": { + "args": "[]" + } + }, + "0xD2F6c828606Ad8e985008Cd825012f269B50CD58": { + "id": "PoseidonT6", + "deploymentTxHash": "0xff9c1393788a82b95c00b037bfac7fcb6857836e604bdadd42049cbf0d88537a", + "verify": { + "args": "[]" + } + }, + "0x982530673Ce9e5Efa02438c694d48327Aa4fB592": { + "id": "PollFactory", + "deploymentTxHash": "0x1a0ba85163df584ea645e3f4de1173d8e7c86d4bd1641b2f6f10d8d2a5cde971", + "verify": { + "args": "[]" + } + }, + "0x50045B05cb1C76410783D8A3e5625a99d5729339": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x85717a2b7f555c5a31d67a401b4c233a216de27c4e8ccbc8ead5ab4241f92dba", + "verify": { + "args": "[]" + } + }, + "0xbB28555E989799478442483CD1f2D370a14e2C42": { + "id": "TallyFactory", + "deploymentTxHash": "0xa7634556c12fb6e039fc189544b61ec5baa8fda94f5499e71751fa57e53c164e", + "verify": { + "args": "[]" + } + }, + "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5": { + "id": "VkRegistry", + "deploymentTxHash": "0x147fe06bd640870ef3e4dca188c89d8c75b35e3ce30bc9b972e0eae573658537", + "verify": { + "args": "[]" + } + }, + "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7": { + "id": "ZupassGatekeeper", + "deploymentTxHash": "0xe6954597b9079895f6facc122e2a0bd9af00bc0401bf6f61d9d7824aed534754", + "verify": { + "args": "[\"280209352117126055869169359893920931853\",\"13908133709081944902758389525983124100292637002438232157513257158004852609027\",\"7654374482676219729919246464135900991450848628968334062174564799457623790084\",\"0xd81aB9859e1d423aC51170256BedD0Aa00e4eD5A\"]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0xB486cce9B4507A67Db147B0802D5673774C8D278", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x83dD551541C580e338206f1f677835D427C92dE2", + "count": 1 + }, + "Verifier": { + "address": "0xD5C41106db85EDd0298279AcFCE5A722060cc5f9", + "count": 1 + }, + "PoseidonT3": { + "address": "0x88C2c6A7535463962A34757FE63cc4F296381aba", + "count": 1 + }, + "PoseidonT4": { + "address": "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66", + "count": 1 + }, + "PoseidonT5": { + "address": "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274", + "count": 1 + }, + "PoseidonT6": { + "address": "0xD2F6c828606Ad8e985008Cd825012f269B50CD58", + "count": 1 + }, + "PollFactory": { + "address": "0x982530673Ce9e5Efa02438c694d48327Aa4fB592", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x50045B05cb1C76410783D8A3e5625a99d5729339", + "count": 1 + }, + "TallyFactory": { + "address": "0xbB28555E989799478442483CD1f2D370a14e2C42", + "count": 1 + }, + "VkRegistry": { + "address": "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5", + "count": 1 + }, + "ZupassGatekeeper": { + "address": "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7", + "count": 1 + } + } + }, + "base": { + "instance": { + "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x242651353bbceb375246239a73005c9d9359754e5739d354ad9f90b76e80be0c", + "verify": { + "args": "[\"200\"]" + } + }, + "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x9bd1a8595f8ab33fac82958a02dd8bfc59756d367c74a0c9d87718fdcf973060", + "verify": { + "args": "[]" + } + }, + "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27": { + "id": "Verifier", + "deploymentTxHash": "0x6eedd506c4339c14df939a98bd15b6e503eecc4e3a693dcb313a56a14ca7d8f9", + "verify": { + "args": "[]" + } + }, + "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4": { + "id": "PoseidonT3", + "deploymentTxHash": "0x0908efdd06741443bd38d57eab6d07daaa15f782a2eba0d485116580da21785d", + "verify": { + "args": "[]" + } + }, + "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6": { + "id": "PoseidonT4", + "deploymentTxHash": "0x4551ba77ad63c28cbf4910e2a3db99b6b8eb1a94e0d902c2366b08a8324b8819", + "verify": { + "args": "[]" + } + }, + "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968": { + "id": "PoseidonT5", + "deploymentTxHash": "0x2dea3913d068f5c365b88da011b542f8c86daa78bff60b0239dfbc1284d8c6ef", + "verify": { + "args": "[]" + } + }, + "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E": { + "id": "PoseidonT6", + "deploymentTxHash": "0x56974c8cae477fba1c16ecebcf2bc929a112471e25e1779cdad3da43b45a6cd2", + "verify": { + "args": "[]" + } + }, + "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607": { + "id": "PollFactory", + "deploymentTxHash": "0x9a9640ccb8a938f97729bfc78e891161082de511c10ab0b62b0e18edd514a017", + "verify": { + "args": "[]" + } + }, + "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x1a23828d513579f09360065323b553de620ae8ce7dfa487dc43397d30700f8fb", + "verify": { + "args": "[]" + } + }, + "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C": { + "id": "TallyFactory", + "deploymentTxHash": "0xa9afd6b34776d392bdeb5a8eea1c4d6692a2c0b000e131b9eecb4b5e0fc2bff6", + "verify": { + "args": "[]" + } + }, + "0x6aA5baD99aC44bB008930c68CE2249549Cf10944": { + "id": "VkRegistry", + "deploymentTxHash": "0x15fd66ac9c193eae37b2b447621ff1d7603a4b55c54c73e0468f900136fc37cb", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f", + "count": 1 + }, + "Verifier": { + "address": "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27", + "count": 1 + }, + "PoseidonT3": { + "address": "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4", + "count": 1 + }, + "PoseidonT4": { + "address": "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6", + "count": 1 + }, + "PoseidonT5": { + "address": "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968", + "count": 1 + }, + "PoseidonT6": { + "address": "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E", + "count": 1 + }, + "PollFactory": { + "address": "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5", + "count": 1 + }, + "TallyFactory": { + "address": "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C", + "count": 1 + }, + "VkRegistry": { + "address": "0x6aA5baD99aC44bB008930c68CE2249549Cf10944", + "count": 1 + } + } + }, + "arbitrum": { + "instance": { + "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x72ef6fcc655bcd8bbc1d545b2a51ab44ce5291bb4fa548259c42de1325145952", + "verify": { + "args": "[\"200\"]" + } + }, + "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x9c0775b0288898a94f27865d46e5bd8872492b5df65cd177b150806aab7560a7", + "verify": { + "args": "[]" + } + }, + "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27": { + "id": "Verifier", + "deploymentTxHash": "0x4a1a77469dff336b80ed4ef8e7482b3a77b9e1c76e92e9bb0c3f3f3229b2ee4c", + "verify": { + "args": "[]" + } + }, + "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4": { + "id": "PoseidonT3", + "deploymentTxHash": "0x1479f77d3c9ccb71d3050097f9caa7c24632814282e1a530d8eefe7e34ab2949", + "verify": { + "args": "[]" + } + }, + "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6": { + "id": "PoseidonT4", + "deploymentTxHash": "0x3d203b3236acec539b1da934f43184924aef0cba84f375febe0919921fbea803", + "verify": { + "args": "[]" + } + }, + "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968": { + "id": "PoseidonT5", + "deploymentTxHash": "0x7a4c8f1809958494685511cf25a70d4e2906bd074843b56ccf5ce5fd96e6f2f9", + "verify": { + "args": "[]" + } + }, + "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E": { + "id": "PoseidonT6", + "deploymentTxHash": "0x75853fcc0e430fdd3c4a7971d4e555161affdf93a7f5a4eaaa93c83c4c1ce94f", + "verify": { + "args": "[]" + } + }, + "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607": { + "id": "PollFactory", + "deploymentTxHash": "0x8315c48647621fa0cee54314ea49bcc851223eabd1f7dc9f3efcf307924ebd69", + "verify": { + "args": "[]" + } + }, + "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x1a30587862f43b3f2cb764cc18e4fbd09a55880bc059471998793ff4e92b6469", + "verify": { + "args": "[]" + } + }, + "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C": { + "id": "TallyFactory", + "deploymentTxHash": "0x960ed63cbea915e39b7dec78d22e83f3d2c710b902262217f2444202356d0880", + "verify": { + "args": "[]" + } + }, + "0x6aA5baD99aC44bB008930c68CE2249549Cf10944": { + "id": "VkRegistry", + "deploymentTxHash": "0xfeaaff43b313214986c4d1f3d3b610f5715be2c17bc10849e3cae776a505bd09", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x16FC13edD59D4b9F788Fb11A70eA022E1Bb1B856", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x8BA83Dd6E0E448417C519A38c90Ee570A4CA3e9f", + "count": 1 + }, + "Verifier": { + "address": "0x2427Ab201488Ac81Bec421F179B1Be23c55ebC27", + "count": 1 + }, + "PoseidonT3": { + "address": "0x2F1398ab5E322d357dF8CdD2e7ba73122c5FDDA4", + "count": 1 + }, + "PoseidonT4": { + "address": "0x8778dA47eF619f56341fE95514e95fa0FF3B77C6", + "count": 1 + }, + "PoseidonT5": { + "address": "0xB8Bc2c7cF71441fF7E6F111D3457e3d61c564968", + "count": 1 + }, + "PoseidonT6": { + "address": "0x37282fEde56aa1d7266Ecb12DC3b342D12044e2E", + "count": 1 + }, + "PollFactory": { + "address": "0x2F1A5B4F8F3B7348C66A1522622b1DB712261607", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xE4c9d4248F1371C5C61d406A9859f9FE667567a5", + "count": 1 + }, + "TallyFactory": { + "address": "0x57034389Dbe3DE1D1C14763f55B77A2279D6d43C", + "count": 1 + }, + "VkRegistry": { + "address": "0x6aA5baD99aC44bB008930c68CE2249549Cf10944", + "count": 1 + } + } + }, + "optimism": { + "instance": { + "0x83dD551541C580e338206f1f677835D427C92dE2": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x44b638a8e359b5014ed77492755ade1d59cf6f5f72f39110c325e7fa463dad6a", + "verify": { + "args": "[\"200\"]" + } + }, + "0xD5C41106db85EDd0298279AcFCE5A722060cc5f9": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x69c745b040908eb98e63065b1f5635d7d5176d0e331d37321c564ed1b6658a5c", + "verify": { + "args": "[]" + } + }, + "0x88C2c6A7535463962A34757FE63cc4F296381aba": { + "id": "Verifier", + "deploymentTxHash": "0x7f25d693564a17029b9bdfc0850a4c8ea30797e2096961558c5e05df4aa8175d", + "verify": { + "args": "[]" + } + }, + "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66": { + "id": "PoseidonT3", + "deploymentTxHash": "0x25e4abb71a79528f8c76bcb83a1163597c80177091667ccb2fd2eb57af84b254", + "verify": { + "args": "[]" + } + }, + "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274": { + "id": "PoseidonT4", + "deploymentTxHash": "0xff394431d7f8985936fc81009a461aa176b4e97a540b031771387e2b3a058ef5", + "verify": { + "args": "[]" + } + }, + "0xD2F6c828606Ad8e985008Cd825012f269B50CD58": { + "id": "PoseidonT5", + "deploymentTxHash": "0x64b18ed067fcd5aa9061255cace422992b0c02207d09a4f78e7182143bb05d88", + "verify": { + "args": "[]" + } + }, + "0x982530673Ce9e5Efa02438c694d48327Aa4fB592": { + "id": "PoseidonT6", + "deploymentTxHash": "0xbb20d4bdc02536ae1435cfcd4b07914161f028063d8cbf66cb8f79b2e2097929", + "verify": { + "args": "[]" + } + }, + "0x50045B05cb1C76410783D8A3e5625a99d5729339": { + "id": "PollFactory", + "deploymentTxHash": "0x65d63100f9eeea80513d6f8513af97e51dca6caf138488eb849f5ae600d2b5b1", + "verify": { + "args": "[]" + } + }, + "0xbB28555E989799478442483CD1f2D370a14e2C42": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x74384358e8fba869c0d4be06e562a93d5020a0685ab428dbbab94068af5a6d4d", + "verify": { + "args": "[]" + } + }, + "0xdA10b22B81eb8EA6BC04aa9b86d3f9d969CD49F0": { + "id": "TallyFactory", + "deploymentTxHash": "0x918e20d6b1c39d921efec9bf8ebcf46ff20449750633350b8a0b9281bb621cd2", + "verify": { + "args": "[]" + } + }, + "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F": { + "id": "VkRegistry", + "deploymentTxHash": "0x197b6b3cc28fda77c36a2b14d44c24f5b8aeff4d009939d200166476656ac521", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x83dD551541C580e338206f1f677835D427C92dE2", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0xD5C41106db85EDd0298279AcFCE5A722060cc5f9", + "count": 1 + }, + "Verifier": { + "address": "0x88C2c6A7535463962A34757FE63cc4F296381aba", + "count": 1 + }, + "PoseidonT3": { + "address": "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66", + "count": 1 + }, + "PoseidonT4": { + "address": "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274", + "count": 1 + }, + "PoseidonT5": { + "address": "0xD2F6c828606Ad8e985008Cd825012f269B50CD58", + "count": 1 + }, + "PoseidonT6": { + "address": "0x982530673Ce9e5Efa02438c694d48327Aa4fB592", + "count": 1 + }, + "PollFactory": { + "address": "0x50045B05cb1C76410783D8A3e5625a99d5729339", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xbB28555E989799478442483CD1f2D370a14e2C42", + "count": 1 + }, + "TallyFactory": { + "address": "0xdA10b22B81eb8EA6BC04aa9b86d3f9d969CD49F0", + "count": 1 + }, + "VkRegistry": { + "address": "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F", + "count": 1 + } + }, + "verified": { + "0x83dD551541C580e338206f1f677835D427C92dE2": true + } + }, + "sepolia": { + "instance": { + "0x88C2c6A7535463962A34757FE63cc4F296381aba": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0xde7be5b9db31e80d77254630c55cc770a232e02c949fa6636c16fb4301f26ff9", + "verify": { + "args": "[\"99\"]" + } + }, + "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x7da5cd7a2c15edc4f8da4d1706995cba1ad77f72f3cfaa74fcbcb5716e0c6aea", + "verify": { + "args": "[]" + } + }, + "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274": { + "id": "Verifier", + "deploymentTxHash": "0x95a162dcc11a4ea83253c7879005f8881532ea47a0c53e6e17f99fab144d2a7c", + "verify": { + "args": "[]" + } + }, + "0xD2F6c828606Ad8e985008Cd825012f269B50CD58": { + "id": "PoseidonT3", + "deploymentTxHash": "0x73a9516529253bab26fdbcb3a07a7e95502a7dbed400ffb31e105ac9af7effbf", + "verify": { + "args": "[]" + } + }, + "0x982530673Ce9e5Efa02438c694d48327Aa4fB592": { + "id": "PoseidonT4", + "deploymentTxHash": "0x3ace926b65edf3a1feed864cc31ebf6eacdf89856c4106d1a613b3a1bcca2172", + "verify": { + "args": "[]" + } + }, + "0x50045B05cb1C76410783D8A3e5625a99d5729339": { + "id": "PoseidonT5", + "deploymentTxHash": "0xdab1329e39d4bb433128c443680c4e37315e3d401e476df99af4a9665c8acd87", + "verify": { + "args": "[]" + } + }, + "0xbB28555E989799478442483CD1f2D370a14e2C42": { + "id": "PoseidonT6", + "deploymentTxHash": "0xf25f2dec66584f9edb29fc66ec1f487c258f557c843fe294c2b997a1d19a310c", + "verify": { + "args": "[]" + } + }, + "0xdA10b22B81eb8EA6BC04aa9b86d3f9d969CD49F0": { + "id": "PollFactory", + "deploymentTxHash": "0x6051c605989e782aa466442ab0f6cf33a02b854137506d1ad69433335a5fe119", + "verify": { + "args": "[]" + } + }, + "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0xc31ca730ab1f011dd98b3e16e60b364770f5dbe8fd2f87473fc54d0cae8505a3", + "verify": { + "args": "[]" + } + }, + "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F": { + "id": "TallyFactory", + "deploymentTxHash": "0xdb2cdbb2a4eb1725cfd200b15c865b74bdf03743eea4cb79984f07f139662d9b", + "verify": { + "args": "[]" + } + }, + "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7": { + "id": "VkRegistry", + "deploymentTxHash": "0xdb5367f5d5bdaaaffa7f52f26af384ba44bb3edd6975471d6f313eb02c34fe56", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x88C2c6A7535463962A34757FE63cc4F296381aba", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0xF8E637e5c9EC3A8d8fa8843A6dF833348E1F1E66", + "count": 1 + }, + "Verifier": { + "address": "0x0a0D66baFDa8c8838281084d9C3d68Dd9a6Fc274", + "count": 1 + }, + "PoseidonT3": { + "address": "0xD2F6c828606Ad8e985008Cd825012f269B50CD58", + "count": 1 + }, + "PoseidonT4": { + "address": "0x982530673Ce9e5Efa02438c694d48327Aa4fB592", + "count": 1 + }, + "PoseidonT5": { + "address": "0x50045B05cb1C76410783D8A3e5625a99d5729339", + "count": 1 + }, + "PoseidonT6": { + "address": "0xbB28555E989799478442483CD1f2D370a14e2C42", + "count": 1 + }, + "PollFactory": { + "address": "0xdA10b22B81eb8EA6BC04aa9b86d3f9d969CD49F0", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5", + "count": 1 + }, + "TallyFactory": { + "address": "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F", + "count": 1 + }, + "VkRegistry": { + "address": "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7", + "count": 1 + } + } + }, + "gnosis-chiado": { + "instance": { + "0x1Cf6eE7c94f980E0dE60Ad741201D4c6Da3090f9": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0xacd5721dfc20c1bfa3812f8cebf0faa6f0a2e3b226f35d7acf528e85750f3846", + "verify": { + "args": "[\"200\"]" + } + }, + "0xb078423e7e046Bf84ec2140bBF7101CD59773Ccf": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x426148cb8a849ce86f463ddddaca602051e9d707d77788e14ace39873f211204", + "verify": { + "args": "[]" + } + }, + "0x9D1C736b5c86d3eB6D9C062D89793C2fEa4bd5da": { + "id": "Verifier", + "deploymentTxHash": "0x48649ead55da178532f2a399ac37e61f291e38a95038af462899d208a1035166", + "verify": { + "args": "[]" + } + }, + "0x11Ac728015427Bed8846f7Be44359E4a95B63390": { + "id": "PoseidonT3", + "deploymentTxHash": "0xe6dbbed30fdafdaae081b2f1ddba5177a513017a2649348090dc9376929f1c5d", + "verify": { + "args": "[]" + } + }, + "0xF85482f8254EFb6a96346756ab81d5582E436d18": { + "id": "PoseidonT4", + "deploymentTxHash": "0xa71d45b1992d9d93000cad35680bb73c4956e33cccf2a3c3111dccd254f72af9", + "verify": { + "args": "[]" + } + }, + "0x9862F690468B7232F5895A2eCF78a1AAa509C992": { + "id": "PoseidonT5", + "deploymentTxHash": "0xc116f9861727091febd386fa7486aae8d10ba7194a4b3317ef451fdeab278b1e", + "verify": { + "args": "[]" + } + }, + "0x41501310360fB771e65Ef7DCA4F48231D9178253": { + "id": "PoseidonT6", + "deploymentTxHash": "0xa29f9f693cbe65b0a735408d204515f843fd01d25bc6633c4446ca1c8a19be99", + "verify": { + "args": "[]" + } + }, + "0xE756e41cB942365437e32FD13F559245F0Df8d4B": { + "id": "PollFactory", + "deploymentTxHash": "0xeb9d4173c54dbebfd46d8d49a9e9df98ab261789e41bcca577cdc0c59b2cb623", + "verify": { + "args": "[]" + } + }, + "0x88E6983f7D21b6A42e57e844893D417Aa8250F30": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x836deb9ed65313c8c73e5db61a12984853fc6b2bdfd36351ddbf34452bc9269f", + "verify": { + "args": "[]" + } + }, + "0x65748179ECd9FC73470D427163e03d4338A1cD8F": { + "id": "TallyFactory", + "deploymentTxHash": "0xbc544eaec1758adca80911a412a88bccd4315fb5748ddd649a1418cc543575d5", + "verify": { + "args": "[]" + } + }, + "0xE47B468E9E9FD8Dd2B0e8327aF720671552b24E2": { + "id": "VkRegistry", + "deploymentTxHash": "0x5f4d262dd0e5f97f0735a012bf1a8540048f34ea1977c96a69664d467568f9d0", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x1Cf6eE7c94f980E0dE60Ad741201D4c6Da3090f9", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0xb078423e7e046Bf84ec2140bBF7101CD59773Ccf", + "count": 1 + }, + "Verifier": { + "address": "0x9D1C736b5c86d3eB6D9C062D89793C2fEa4bd5da", + "count": 1 + }, + "PoseidonT3": { + "address": "0x11Ac728015427Bed8846f7Be44359E4a95B63390", + "count": 1 + }, + "PoseidonT4": { + "address": "0xF85482f8254EFb6a96346756ab81d5582E436d18", + "count": 1 + }, + "PoseidonT5": { + "address": "0x9862F690468B7232F5895A2eCF78a1AAa509C992", + "count": 1 + }, + "PoseidonT6": { + "address": "0x41501310360fB771e65Ef7DCA4F48231D9178253", + "count": 1 + }, + "PollFactory": { + "address": "0xE756e41cB942365437e32FD13F559245F0Df8d4B", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x88E6983f7D21b6A42e57e844893D417Aa8250F30", + "count": 1 + }, + "TallyFactory": { + "address": "0x65748179ECd9FC73470D427163e03d4338A1cD8F", + "count": 1 + }, + "VkRegistry": { + "address": "0xE47B468E9E9FD8Dd2B0e8327aF720671552b24E2", + "count": 1 + } + } + }, + "gnosis": { + "instance": { + "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x9d48aa401d49d2674a8b6bdc7f8de0ea2f03c9b6bb0bc19b2ba3d54017c7804f", + "verify": { + "args": "[\"200\"]" + } + }, + "0x9e98cAA76492338627BAD0e5a6AA2762d827E169": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0xb9c5a75f51f0224509c6bb975868688ee91dd294791f4cf39ce3f03e3e7aa410", + "verify": { + "args": "[]" + } + }, + "0xB400794f463d90ce5f462A43d8E6f9155656d02d": { + "id": "Verifier", + "deploymentTxHash": "0xc05c712550422873544841dfdec46ffce75d46025e58331e78ec9044ae5416c7", + "verify": { + "args": "[]" + } + }, + "0xa0e0aC07c211D329ebA2D6ec552F4dC1B230A89A": { + "id": "PoseidonT3", + "deploymentTxHash": "0x68c84961d70679e895ded0e5c79cc81b5cf764bfab91319ec12b6272b6e01dd4", + "verify": { + "args": "[]" + } + }, + "0x0CC8B7Aed7d79a8B948636242706265548D0B10a": { + "id": "PoseidonT4", + "deploymentTxHash": "0xd44538216a618fe96f21ea7b6f9ff0da5109c2b2ef90e8507b779e298bc08e2b", + "verify": { + "args": "[]" + } + }, + "0x43B519FF023757508311518AC41B5fA1CfD57181": { + "id": "PoseidonT5", + "deploymentTxHash": "0xc15324656c232c7b650d2e21326cea7e2055f98ce53d94eb8e675b192d0c91bd", + "verify": { + "args": "[]" + } + }, + "0xb123798B1b21082100D289BeA24bFF0F8dfcbEe1": { + "id": "PoseidonT6", + "deploymentTxHash": "0x6dc6b044dae39a104c48305eb3359d0dae722a2315efdcdf4e0c2eeecc077ec6", + "verify": { + "args": "[]" + } + }, + "0xBa350B0cF67a0dEDa103A5d0d297bd120bF87E39": { + "id": "PollFactory", + "deploymentTxHash": "0x37a15ca276ec0bf23ef3b21d30083fba84b536663f613e87d2193edf381cd949", + "verify": { + "args": "[]" + } + }, + "0x96FD5e4E40671Bf8d5f1d0E3F3402488680B8376": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x709583260d64db05493d65e99b82c5cd1c2dcd6631de466b4296af8991ad9651", + "verify": { + "args": "[]" + } + }, + "0xEEBc671e15B3f1c7483161F866d76ad84645d7C8": { + "id": "TallyFactory", + "deploymentTxHash": "0x12ed4b1631115199f4d04bc2af92521953f7a69f5dce698768501b3f33320ca4", + "verify": { + "args": "[]" + } + }, + "0xE21F9Ea298b62032B3C2206955cd12c4Ab0a046b": { + "id": "VkRegistry", + "deploymentTxHash": "0x2b143ecfb9c643f7ffc3d8d3b7c16aacb2057382079970b62e4a7d9280944b34", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x9e98cAA76492338627BAD0e5a6AA2762d827E169", + "count": 1 + }, + "Verifier": { + "address": "0xB400794f463d90ce5f462A43d8E6f9155656d02d", + "count": 1 + }, + "PoseidonT3": { + "address": "0xa0e0aC07c211D329ebA2D6ec552F4dC1B230A89A", + "count": 1 + }, + "PoseidonT4": { + "address": "0x0CC8B7Aed7d79a8B948636242706265548D0B10a", + "count": 1 + }, + "PoseidonT5": { + "address": "0x43B519FF023757508311518AC41B5fA1CfD57181", + "count": 1 + }, + "PoseidonT6": { + "address": "0xb123798B1b21082100D289BeA24bFF0F8dfcbEe1", + "count": 1 + }, + "PollFactory": { + "address": "0xBa350B0cF67a0dEDa103A5d0d297bd120bF87E39", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x96FD5e4E40671Bf8d5f1d0E3F3402488680B8376", + "count": 1 + }, + "TallyFactory": { + "address": "0xEEBc671e15B3f1c7483161F866d76ad84645d7C8", + "count": 1 + }, + "VkRegistry": { + "address": "0xE21F9Ea298b62032B3C2206955cd12c4Ab0a046b", + "count": 1 + } + } + }, + "polygon-amoy": { + "instance": { + "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x85478d9ce20d0b1db965aead2ee6ea07e5e4ed8c5fd7200e28104561d01b00b0", + "verify": { + "args": "[\"200\"]" + } + }, + "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0xa21de26515a57b8a3b3f04511d490b555fef8c4e880ebba5045a45dbc637cb3f", + "verify": { + "args": "[]" + } + }, + "0xd81aB9859e1d423aC51170256BedD0Aa00e4eD5A": { + "id": "Verifier", + "deploymentTxHash": "0x7d6c7aeed8477c17270086aa6bb63c83799b5569d582299a5e0859fc30cdaf07", + "verify": { + "args": "[]" + } + }, + "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7": { + "id": "PoseidonT3", + "deploymentTxHash": "0x5d6eda8b24b826ef377efa3d0d606b1f7b71fe851cced25b62f14b1fb6b0e3ca", + "verify": { + "args": "[]" + } + }, + "0xfcaFB222bd61556E393058F08d6d86bdEbcCE72c": { + "id": "PoseidonT4", + "deploymentTxHash": "0x589fa59ca59b9539ac116dca69295a4991055b7ae113e17be2a731c56418e82d", + "verify": { + "args": "[]" + } + }, + "0xC22411B2a05A9e8D3E6D5C6335B7EEFE3326B463": { + "id": "PoseidonT5", + "deploymentTxHash": "0x17cf2076f874acbfd4531204a9d0d4dc9501914887db02b9fc09c4dc55db170e", + "verify": { + "args": "[]" + } + }, + "0x5AF94C036c47aEEA21f10B721f6A32d82f127B7b": { + "id": "PoseidonT6", + "deploymentTxHash": "0x92d79444ada1b4ac9d2ca99f871f59dc20dc8c036c6c83b4b6e04722779d74d7", + "verify": { + "args": "[]" + } + }, + "0x31b7Befe18B90Dbc2115aE7A27099251341FE09f": { + "id": "PollFactory", + "deploymentTxHash": "0xf65cc72a6837032d825de79c4e4c736497f49bb4c2134de2b8cdd21235ccad09", + "verify": { + "args": "[]" + } + }, + "0x30339f46f1b46d1FbB84cE2ffC2efD2D0CD6E7a3": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0x9f3a3df914f7462f399632e2cfb13116678aa34ce4063b7c1725e8b1ec2904c4", + "verify": { + "args": "[]" + } + }, + "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9": { + "id": "TallyFactory", + "deploymentTxHash": "0xae87d4c5591aaf6cdfcfb48b350eeac6ae948997d5fb8cb35f38c8133ec4dc64", + "verify": { + "args": "[]" + } + }, + "0xB400794f463d90ce5f462A43d8E6f9155656d02d": { + "id": "VkRegistry", + "deploymentTxHash": "0x4bdcfa66c2c04eca5864a44c898d5c64fefcb64bca85e1f90619ebf50e8ac767", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x3D4C58074DCD8E6526885F465ab5F311b6B290B5", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x7E16271EaE58F52a0431F87Ee7E40c978178C63F", + "count": 1 + }, + "Verifier": { + "address": "0xd81aB9859e1d423aC51170256BedD0Aa00e4eD5A", + "count": 1 + }, + "PoseidonT3": { + "address": "0x33Cc5e8b6f158B9ee3600EcD3f3DE76c6B7765a7", + "count": 1 + }, + "PoseidonT4": { + "address": "0xfcaFB222bd61556E393058F08d6d86bdEbcCE72c", + "count": 1 + }, + "PoseidonT5": { + "address": "0xC22411B2a05A9e8D3E6D5C6335B7EEFE3326B463", + "count": 1 + }, + "PoseidonT6": { + "address": "0x5AF94C036c47aEEA21f10B721f6A32d82f127B7b", + "count": 1 + }, + "PollFactory": { + "address": "0x31b7Befe18B90Dbc2115aE7A27099251341FE09f", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0x30339f46f1b46d1FbB84cE2ffC2efD2D0CD6E7a3", + "count": 1 + }, + "TallyFactory": { + "address": "0x41a29A58A63A998c9Edde6883Bcec2d89835a8e9", + "count": 1 + }, + "VkRegistry": { + "address": "0xB400794f463d90ce5f462A43d8E6f9155656d02d", + "count": 1 + } + } + }, + "polygon": { + "instance": { + "0x6d1b05EcD959cD11fAa07ED0537395FE1D39eAc5": { + "id": "ConstantInitialVoiceCreditProxy", + "deploymentTxHash": "0x06cb4d913ad211111bef645e3346e30657a5c9ef686b8afb949d8cfee4c6c158", + "verify": { + "args": "[\"200\"]" + } + }, + "0x4241540530d25A83c920CB48e69CcA9D47eE0687": { + "id": "FreeForAllGatekeeper", + "deploymentTxHash": "0x9f4d39e9bcae1eecf839cf59b8d86b93569727de8ca768f40fb00bf3d64417d8", + "verify": { + "args": "[]" + } + }, + "0x16eE00033D863c00cFaf37d35d86CFAa7CCF7057": { + "id": "Verifier", + "deploymentTxHash": "0x1e4c95ff90d47ca0e255c1f4d7eae68b02de19ca380b3121d3ca63fc37942943", + "verify": { + "args": "[]" + } + }, + "0x2018747cA1574ccCadA63Dc55d16B79e983C4Aa7": { + "id": "PoseidonT3", + "deploymentTxHash": "0x30aec42624d4ea3e972c25d82b52bbf7f1e1f1cd60f42b8362ab241f2717ab2a", + "verify": { + "args": "[]" + } + }, + "0x2941105833E4fcD3aB0D6610Fed9B6FfFe2ba45B": { + "id": "PoseidonT4", + "deploymentTxHash": "0x0cc1cb2a4e475b9a8139837334b65c2bec41024e2110de7eda721b267d415fc3", + "verify": { + "args": "[]" + } + }, + "0x13De8DFb45aD435D55406Cdd0E4F35eddB4e0d55": { + "id": "PoseidonT5", + "deploymentTxHash": "0x4c3b946fdf7d5a34d65b17d0c2214a2e6ac761aa72aa1e735c5cb6a39cb8183f", + "verify": { + "args": "[]" + } + }, + "0x0339e0E6df1F6B592060fa6FE2301a91C9d0b68a": { + "id": "PoseidonT6", + "deploymentTxHash": "0x9010ad974372bf57b8b88ead0aaf32b7823b4c8977be175dbc7558debc68bc2a", + "verify": { + "args": "[]" + } + }, + "0x9F9303200658cB14F220b453a076B3AC4AEf4895": { + "id": "PollFactory", + "deploymentTxHash": "0x73993638b2ee6829f7e399eb813b64ee86ce7bfdbe0f2a6067f100a0de4b952a", + "verify": { + "args": "[]" + } + }, + "0xE1Bc8c8692683A0D145c7FB6292bB44AFd9c5cCD": { + "id": "MessageProcessorFactory", + "deploymentTxHash": "0xeee48d2d6eac893e0f02ef8bb18d2709bb7a1ecdcb88a35e1594d9e7a49858ca", + "verify": { + "args": "[]" + } + }, + "0x28a8F18b19bF3Ec051B8f070416e28e4D3006bD1": { + "id": "TallyFactory", + "deploymentTxHash": "0x52d83a8ee827c78e6994267ec2ab922df2f5ed94eebe33a75a7ce1dcdf3cbf64", + "verify": { + "args": "[]" + } + }, + "0x7F2aDE88ca1D74678356D79b8A6E8550aC31a8F0": { + "id": "VkRegistry", + "deploymentTxHash": "0x76c6ec1c7722003496e5e220ff9908ae20e5c9bec3eaccbc92023a97cda5e66b", + "verify": { + "args": "[]" + } + } + }, + "named": { + "ConstantInitialVoiceCreditProxy": { + "address": "0x6d1b05EcD959cD11fAa07ED0537395FE1D39eAc5", + "count": 1 + }, + "FreeForAllGatekeeper": { + "address": "0x4241540530d25A83c920CB48e69CcA9D47eE0687", + "count": 1 + }, + "Verifier": { + "address": "0x16eE00033D863c00cFaf37d35d86CFAa7CCF7057", + "count": 1 + }, + "PoseidonT3": { + "address": "0x2018747cA1574ccCadA63Dc55d16B79e983C4Aa7", + "count": 1 + }, + "PoseidonT4": { + "address": "0x2941105833E4fcD3aB0D6610Fed9B6FfFe2ba45B", + "count": 1 + }, + "PoseidonT5": { + "address": "0x13De8DFb45aD435D55406Cdd0E4F35eddB4e0d55", + "count": 1 + }, + "PoseidonT6": { + "address": "0x0339e0E6df1F6B592060fa6FE2301a91C9d0b68a", + "count": 1 + }, + "PollFactory": { + "address": "0x9F9303200658cB14F220b453a076B3AC4AEf4895", + "count": 1 + }, + "MessageProcessorFactory": { + "address": "0xE1Bc8c8692683A0D145c7FB6292bB44AFd9c5cCD", + "count": 1 + }, + "TallyFactory": { + "address": "0x28a8F18b19bF3Ec051B8f070416e28e4D3006bD1", + "count": 1 + }, + "VkRegistry": { + "address": "0x7F2aDE88ca1D74678356D79b8A6E8550aC31a8F0", + "count": 1 + } + } + } +} diff --git a/packages/coordinator/tests/e2e.aa.test.ts b/packages/coordinator/tests/e2e.aa.test.ts index 080e5923..2bb8bc26 100644 --- a/packages/coordinator/tests/e2e.aa.test.ts +++ b/packages/coordinator/tests/e2e.aa.test.ts @@ -6,7 +6,7 @@ import { addressToEmptyAccount, createKernelAccount } from "@zerodev/sdk"; import { KERNEL_V3_1 } from "@zerodev/sdk/constants"; import dotenv from "dotenv"; import { ENTRYPOINT_ADDRESS_V07 } from "permissionless"; -import { Hex } from "viem"; +import { Hex, zeroAddress } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { ErrorCodes, ESupportedNetworks } from "../ts/common"; @@ -14,6 +14,8 @@ import { getPublicClient } from "../ts/common/accountAbstraction"; import { CryptoService } from "../ts/crypto/crypto.service"; import { FileService } from "../ts/file/file.service"; import { ProofGeneratorService } from "../ts/proof/proof.service"; +import { testMaciDeploymentConfig, testPollDeploymentConfig } from "../ts/deployer/__tests__/utils"; +import { DeployerService } from "../ts/deployer/deployer.service"; import { SessionKeysService } from "../ts/sessionKeys/sessionKeys.service"; dotenv.config(); @@ -24,6 +26,7 @@ const kernelVersion = KERNEL_V3_1; /** * Generate an approval for a session key * + * @param sessionKeyAddress - the session key address * @returns - the approval */ export const generateApproval = async (sessionKeyAddress: Hex): Promise => { @@ -63,38 +66,118 @@ describe("E2E Account Abstraction Tests", () => { const sessionKeyService = new SessionKeysService(fileService); const cryptoService = new CryptoService(); const proofService = new ProofGeneratorService(cryptoService, fileService, sessionKeyService); + const deployerService = new DeployerService(sessionKeyService, fileService); // using an already deployed maci contract const maciContract = "0xf281870519822f302B13c07252d0f6A71E8D023e"; const pollId = 2; - test("should return true when there are no errors", async () => { - const sessionKey = sessionKeyService.generateSessionKey().sessionKeyAddress; - const approval = await generateApproval(sessionKey); + const { sessionKeyAddress } = sessionKeyService.generateSessionKey(); - const merged = await proofService.merge({ - maciContractAddress: maciContract, - pollId, - sessionKeyAddress: sessionKey, - approval, - chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + let approval: string; + + beforeAll(async () => { + approval = await generateApproval(sessionKeyAddress); + }); + + describe("deploy", () => { + describe("deployMaci", () => { + it("should deploy all maci related contracts", async () => { + const maciAddress = await deployerService.deployMaci({ + approval, + sessionKeyAddress, + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + config: testMaciDeploymentConfig, + }); + + expect(maciAddress).not.toBe(zeroAddress); + }); }); - expect(merged).toBe(true); + describe("deployPoll", () => { + it("should deploy a poll", async () => { + const poll = await deployerService.deployPoll({ + approval, + sessionKeyAddress, + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + config: testPollDeploymentConfig, + }); + + expect(poll).toBeDefined(); + }); + }); }); - test("should throw when given an invalid pollId", async () => { - const sessionKey = sessionKeyService.generateSessionKey().sessionKeyAddress; - const approval = await generateApproval(sessionKey); + describe("merge", () => { + test("should return true when there are no errors", async () => { + const sessionKey = sessionKeyService.generateSessionKey().sessionKeyAddress; + const approval = await generateApproval(sessionKey); - await expect( - proofService.merge({ + const merged = await proofService.merge({ maciContractAddress: maciContract, - pollId: 50000, + pollId, sessionKeyAddress: sessionKey, approval, chain: ESupportedNetworks.OPTIMISM_SEPOLIA, - }), - ).rejects.toThrow(ErrorCodes.POLL_NOT_FOUND); + }); + + expect(merged).toBe(true); + }); + + test("should throw when given an invalid pollId", async () => { + const sessionKey = sessionKeyService.generateSessionKey().sessionKeyAddress; + const approval = await generateApproval(sessionKey); + + await expect( + proofService.merge({ + maciContractAddress: maciContract, + pollId: 50000, + sessionKeyAddress: sessionKey, + approval, + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + }), + ).rejects.toThrow(ErrorCodes.POLL_NOT_FOUND); + }); + }); + + describe("sessionKeys", () => { + it("should create a client from a session key and an approval", async () => { + const client = await sessionKeyService.generateClientFromSessionKey( + sessionKeyAddress, + approval, + ESupportedNetworks.OPTIMISM_SEPOLIA, + ); + + expect(client).toBeDefined(); + expect(client.transport.key).toBe("http"); + expect(client.key).toBe("Account"); + expect(client.account.address).not.toBe(zeroAddress); + expect(client.account.kernelVersion).toBe(kernelVersion); + expect(client.account.entryPoint).toBe(entryPoint); + // this is an account with limited permissions so no sudo validator + expect(client.account.kernelPluginManager.address).toBe(zeroAddress); + expect(client.account.kernelPluginManager.sudoValidator).toBe(undefined); + + // send a transaction + const tx = await client.sendTransaction({ + to: zeroAddress, + value: 0n, + data: "0x", + }); + + expect(tx.length).toBeGreaterThan(0); + }); + + it("should not allow to create a client after the session key has been deactivated", async () => { + sessionKeyService.deactivateSessionKey(sessionKeyAddress); + + await expect( + sessionKeyService.generateClientFromSessionKey( + sessionKeyAddress, + approval, + ESupportedNetworks.OPTIMISM_SEPOLIA, + ), + ).rejects.toThrow(ErrorCodes.SESSION_KEY_NOT_FOUND); + }); }); }); diff --git a/packages/coordinator/ts/app.module.ts b/packages/coordinator/ts/app.module.ts index fdd623a5..5364d74c 100644 --- a/packages/coordinator/ts/app.module.ts +++ b/packages/coordinator/ts/app.module.ts @@ -2,6 +2,7 @@ import { Module } from "@nestjs/common"; import { ThrottlerModule } from "@nestjs/throttler"; import { CryptoModule } from "./crypto/crypto.module"; +import { DeployerModule } from "./deployer/deployer.module"; import { FileModule } from "./file/file.module"; import { ProofModule } from "./proof/proof.module"; import { SessionKeysModule } from "./sessionKeys/sessionKeys.module"; @@ -20,6 +21,7 @@ import { SubgraphModule } from "./subgraph/subgraph.module"; SubgraphModule, ProofModule, SessionKeysModule, + DeployerModule, ], }) export class AppModule {} diff --git a/packages/coordinator/ts/common/__tests__/common.test.ts b/packages/coordinator/ts/common/__tests__/common.test.ts index cc9a7b29..254fad2d 100644 --- a/packages/coordinator/ts/common/__tests__/common.test.ts +++ b/packages/coordinator/ts/common/__tests__/common.test.ts @@ -1,7 +1,92 @@ -import { genPimlicoRPCUrl } from "../accountAbstraction"; +import { + mainnet, + sepolia, + arbitrum, + arbitrumSepolia, + baseSepolia, + lineaSepolia, + scrollSepolia, + scroll, + base, + holesky, + linea, + bsc, + gnosis, + polygon, + optimism, + optimismSepolia, +} from "viem/chains"; + +import type { TransactionReceipt } from "viem"; + +import { + genAlchemyRPCUrl, + genPimlicoRPCUrl, + getBundlerClient, + getDeployedContractAddress, + getPublicClient, + getZeroDevBundlerRPCUrl, +} from "../accountAbstraction"; import { ErrorCodes } from "../errors"; +import { ESupportedNetworks, viemChain } from "../networks"; describe("common", () => { + describe("getPublicClient", () => { + test("should return a public client", () => { + const publicClient = getPublicClient(ESupportedNetworks.OPTIMISM_SEPOLIA); + expect(publicClient).toBeDefined(); + }); + + test("should throw when given an unsupported network", () => { + expect(() => getPublicClient("Unsupported" as ESupportedNetworks)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK); + }); + }); + + describe("getZeroDevBundlerRPCUrl", () => { + test("should throw when the network is not supported", () => { + expect(() => getZeroDevBundlerRPCUrl("Unsupported" as ESupportedNetworks)).toThrow( + ErrorCodes.UNSUPPORTED_NETWORK, + ); + }); + + test("should return an RPCUrl for a supported network", () => { + const rpcUrlOPS = getZeroDevBundlerRPCUrl(ESupportedNetworks.OPTIMISM_SEPOLIA); + expect(rpcUrlOPS).toBeDefined(); + + const rpcUrlOP = getZeroDevBundlerRPCUrl(ESupportedNetworks.OPTIMISM); + expect(rpcUrlOP).toBeDefined(); + }); + }); + + describe("getBundlerClient", () => { + test("should throw when the network is not supported", () => { + expect(() => getBundlerClient("Unsupported" as ESupportedNetworks)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK); + }); + }); + + describe("genAlchemyRPCUrl", () => { + test("should return the correct RPCUrl for optimism-sepolia", () => { + const rpcUrl = genAlchemyRPCUrl(ESupportedNetworks.OPTIMISM_SEPOLIA); + expect(rpcUrl).toBeDefined(); + expect(rpcUrl).toContain("https://opt-sepolia.g.alchemy.com/v2/"); + }); + + test("should return the correct RPCUrl for sepolia", () => { + const rpcUrl = genAlchemyRPCUrl(ESupportedNetworks.ETHEREUM_SEPOLIA); + expect(rpcUrl).toBeDefined(); + expect(rpcUrl).toContain("https://eth-sepolia.g.alchemy.com/v2/"); + }); + + test("should throw when given an unsupported network", () => { + expect(() => genAlchemyRPCUrl(ESupportedNetworks.GNOSIS_CHAIN)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK); + }); + + test("should throw when ALCHEMY_API_KEY is not set", () => { + delete process.env.RPC_API_KEY; + expect(() => genAlchemyRPCUrl(ESupportedNetworks.OPTIMISM_SEPOLIA)).toThrow(ErrorCodes.RPC_API_KEY_NOT_SET); + }); + }); + describe("genPimlicoRPCUrl", () => { test("should return the correct RPCUrl", () => { const rpcUrl = genPimlicoRPCUrl("optimism-sepolia"); @@ -14,4 +99,35 @@ describe("common", () => { expect(() => genPimlicoRPCUrl("optimism-sepolia")).toThrow(ErrorCodes.PIMLICO_API_KEY_NOT_SET); }); }); + + describe("getDeployedContractAddress", () => { + test("should throw when the log is undefined", () => { + expect(() => getDeployedContractAddress({} as TransactionReceipt)).toThrow(); + }); + }); + + describe("viemChain", () => { + test("should return correct chain for all supported networks", () => { + expect(viemChain(ESupportedNetworks.ETHEREUM)).toBe(mainnet); + expect(viemChain(ESupportedNetworks.ETHEREUM_SEPOLIA)).toBe(sepolia); + expect(viemChain(ESupportedNetworks.ARBITRUM_ONE)).toBe(arbitrum); + expect(viemChain(ESupportedNetworks.ARBITRUM_SEPOLIA)).toBe(arbitrumSepolia); + expect(viemChain(ESupportedNetworks.BASE_SEPOLIA)).toBe(baseSepolia); + expect(viemChain(ESupportedNetworks.LINEA_SEPOLIA)).toBe(lineaSepolia); + expect(viemChain(ESupportedNetworks.SCROLL_SEPOLIA)).toBe(scrollSepolia); + expect(viemChain(ESupportedNetworks.SCROLL)).toBe(scroll); + expect(viemChain(ESupportedNetworks.BASE)).toBe(base); + expect(viemChain(ESupportedNetworks.HOLESKY)).toBe(holesky); + expect(viemChain(ESupportedNetworks.LINEA)).toBe(linea); + expect(viemChain(ESupportedNetworks.BSC)).toBe(bsc); + expect(viemChain(ESupportedNetworks.GNOSIS_CHAIN)).toBe(gnosis); + expect(viemChain(ESupportedNetworks.POLYGON)).toBe(polygon); + expect(viemChain(ESupportedNetworks.OPTIMISM)).toBe(optimism); + expect(viemChain(ESupportedNetworks.OPTIMISM_SEPOLIA)).toBe(optimismSepolia); + }); + + test("should throw error for unsupported network", () => { + expect(() => viemChain("UNSUPPORTED_NETWORK" as ESupportedNetworks)).toThrow(ErrorCodes.UNSUPPORTED_NETWORK); + }); + }); }); diff --git a/packages/coordinator/ts/common/accountAbstraction.ts b/packages/coordinator/ts/common/accountAbstraction.ts index bb06ea84..4432a58b 100644 --- a/packages/coordinator/ts/common/accountAbstraction.ts +++ b/packages/coordinator/ts/common/accountAbstraction.ts @@ -1,12 +1,8 @@ -import { deserializePermissionAccount } from "@zerodev/permissions"; -import { toECDSASigner } from "@zerodev/permissions/signers"; -import { createKernelAccountClient, KernelAccountClient, KernelSmartAccount } from "@zerodev/sdk"; -import { KERNEL_V3_1 } from "@zerodev/sdk/constants"; +import { BundlerClient, createBundlerClient, ENTRYPOINT_ADDRESS_V07 } from "permissionless"; +import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "permissionless/types"; +import { createPublicClient, http, type HttpTransport, type TransactionReceipt, type PublicClient, Chain } from "viem"; + import dotenv from "dotenv"; -import { ENTRYPOINT_ADDRESS_V07 } from "permissionless"; -import { ENTRYPOINT_ADDRESS_V07_TYPE } from "permissionless/types"; -import { createPublicClient, http, type HttpTransport, type Transport, type Hex, type PublicClient, Chain } from "viem"; -import { privateKeyToAccount } from "viem/accounts"; import { ErrorCodes } from "./errors"; import { ESupportedNetworks, viemChain } from "./networks"; @@ -65,47 +61,54 @@ export const getPublicClient = (chainName: ESupportedNetworks): PublicClient - > -> => { - const bundlerUrl = genPimlicoRPCUrl(chain); - const publicClient = getPublicClient(chain); - - // Using a stored private key - const sessionKeySigner = toECDSASigner({ - signer: privateKeyToAccount(sessionKey), - }); - - const sessionKeyAccount = await deserializePermissionAccount( - publicClient, - ENTRYPOINT_ADDRESS_V07, - KERNEL_V3_1, - approval, - sessionKeySigner, - ); +export const getZeroDevBundlerRPCUrl = (network: ESupportedNetworks): string => { + switch (network) { + case ESupportedNetworks.OPTIMISM_SEPOLIA: + return process.env.ZERODEV_BUNDLER_RPC_OP_SEPOLIA || ""; + case ESupportedNetworks.OPTIMISM: + return process.env.ZERODEV_BUNDLER_RPC_OP || ""; + default: + throw new Error(ErrorCodes.UNSUPPORTED_NETWORK); + } +}; - const kernelClient = createKernelAccountClient({ - bundlerTransport: http(bundlerUrl), +/** + * Get a bundler client + * + * @param chainName - the chain name + * @returns the bundler client + */ +export const getBundlerClient = (chainName: ESupportedNetworks): BundlerClient => + createBundlerClient({ + transport: http(genPimlicoRPCUrl(chainName)), + chain: viemChain(chainName), entryPoint: ENTRYPOINT_ADDRESS_V07, - account: sessionKeyAccount, - chain: viemChain(chain), }); - return kernelClient; +/** + * The topic for the contract creation event + */ +export const contractCreationEventTopic = "0x4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b511"; + +/** + * The offset for the address in the contract creation event + */ +export const addressOffset = 26; + +/** + * Get the address of the newly deployed contract from a transaction receipt + * @param receipt - The transaction receipt + * @returns The address of the newly deployed contract + */ +export const getDeployedContractAddress = (receipt: TransactionReceipt): string | undefined => { + const addr = receipt.logs.find((log) => log.topics[0] === contractCreationEventTopic); + + const deployedAddress = addr ? `0x${addr.topics[1]?.slice(addressOffset)}` : undefined; + + return deployedAddress; }; diff --git a/packages/coordinator/ts/common/errors.ts b/packages/coordinator/ts/common/errors.ts index 2e9732c4..e9b137a5 100644 --- a/packages/coordinator/ts/common/errors.ts +++ b/packages/coordinator/ts/common/errors.ts @@ -12,10 +12,20 @@ export enum ErrorCodes { SUBGRAPH_DEPLOY = "7", SESSION_KEY_NOT_FOUND = "8", PIMLICO_API_KEY_NOT_SET = "9", - INVALID_APPROVAL = "10", - UNSUPPORTED_NETWORK = "11", - RPC_API_KEY_NOT_SET = "12", - FAILED_TO_MERGE_STATE_TREE = "13", - FAILED_TO_MERGE_MESSAGE_SUBTREES = "14", - FAILED_TO_MERGE_MESSAGE_TREE = "15", + UNSUPPORTED_VOICE_CREDIT_PROXY = "10", + UNSUPPORTED_GATEKEEPER = "11", + FAILED_TO_DEPLOY_CONTRACT = "12", + FAILED_TO_SET_MACI_INSTANCE_ON_GATEKEEPER = "13", + INVALID_APPROVAL = "14", + MACI_NOT_DEPLOYED = "15", + VERIFIER_NOT_DEPLOYED = "16", + VK_REGISTRY_NOT_DEPLOYED = "17", + FAILED_TO_SET_VERIFYING_KEYS_ON_VK_REGISTRY = "18", + UNSUPPORTED_NETWORK = "19", + RPC_API_KEY_NOT_SET = "20", + FAILED_TO_DEPLOY_MACI = "21", + FAILED_TO_DEPLOY_POLL = "22", + FAILED_TO_MERGE_STATE_TREE = "23", + FAILED_TO_MERGE_MESSAGE_SUBTREES = "24", + FAILED_TO_MERGE_MESSAGE_TREE = "25", } diff --git a/packages/coordinator/ts/common/index.ts b/packages/coordinator/ts/common/index.ts index b3ecbda8..88789a24 100644 --- a/packages/coordinator/ts/common/index.ts +++ b/packages/coordinator/ts/common/index.ts @@ -1,3 +1,4 @@ export { ErrorCodes } from "./errors"; export { ESupportedNetworks } from "./networks"; export { transformToString } from "./utils"; +export const MESSAGE_TREE_ARITY = 5n; diff --git a/packages/coordinator/ts/common/networks.ts b/packages/coordinator/ts/common/networks.ts index f1ea30c9..e4b03930 100644 --- a/packages/coordinator/ts/common/networks.ts +++ b/packages/coordinator/ts/common/networks.ts @@ -19,6 +19,8 @@ import { sepolia, } from "viem/chains"; +import { ErrorCodes } from "./errors"; + export enum ESupportedNetworks { ETHEREUM = "mainnet", OPTIMISM = "optimism", @@ -83,6 +85,6 @@ export const viemChain = (network: ESupportedNetworks): Chain => { case ESupportedNetworks.LOCALHOST: return localhost; default: - throw new Error(`Unsupported network: ${network}`); + throw new Error(ErrorCodes.UNSUPPORTED_NETWORK); } }; diff --git a/packages/coordinator/ts/deployer/__tests__/deployer.controller.test.ts b/packages/coordinator/ts/deployer/__tests__/deployer.controller.test.ts new file mode 100644 index 00000000..d7486b48 --- /dev/null +++ b/packages/coordinator/ts/deployer/__tests__/deployer.controller.test.ts @@ -0,0 +1,96 @@ +import { Test } from "@nestjs/testing"; +import { zeroAddress } from "viem"; + +import { ErrorCodes, ESupportedNetworks } from "../../common"; +import { FileService } from "../../file/file.service"; +import { SessionKeysService } from "../../sessionKeys/sessionKeys.service"; +import { DeployerController } from "../deployer.controller"; +import { DeployerService } from "../deployer.service"; + +import { testMaciDeploymentConfig, testPollDeploymentConfig } from "./utils"; + +describe("DeployerController", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + let deployerController: DeployerController; + + const mockDeployerService = { + deployMaci: jest.fn(), + deployPoll: jest.fn(), + }; + + const defaultDeployMaciReturn: string = zeroAddress; + const defaultDeployPollReturn = "0"; + + const deployerControllerFail = new DeployerController( + new DeployerService(new SessionKeysService(new FileService()), new FileService()), + ); + + beforeEach(async () => { + const app = await Test.createTestingModule({ + controllers: [DeployerController], + }) + .useMocker((token) => { + if (token === DeployerService) { + mockDeployerService.deployMaci.mockResolvedValue(defaultDeployMaciReturn); + mockDeployerService.deployPoll.mockResolvedValue(defaultDeployPollReturn); + return mockDeployerService; + } + + return jest.fn(); + }) + .compile(); + + deployerController = app.get(DeployerController); + }); + + describe("v1/deploy/maci", () => { + test("should deploy all contract", async () => { + const response = await deployerController.deployMACIContracts({ + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + approval: "", + sessionKeyAddress: "0x", + config: testMaciDeploymentConfig, + }); + + expect(response).toEqual(defaultDeployMaciReturn); + }); + + test("should return 400 bad request when the service throws", async () => { + await expect( + deployerControllerFail.deployMACIContracts({ + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + approval: "", + sessionKeyAddress: "0x", + config: testMaciDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.SESSION_KEY_NOT_FOUND); + }); + }); + + describe("v1/deploy/poll", () => { + test("should deploy a new poll", async () => { + const response = await deployerController.deployPoll({ + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + approval: "", + sessionKeyAddress: "0x", + config: testPollDeploymentConfig, + }); + + expect(response).toEqual(defaultDeployPollReturn); + }); + + test("should return 400 bad request when the service throws", async () => { + await expect( + deployerControllerFail.deployPoll({ + chain: ESupportedNetworks.OPTIMISM_SEPOLIA, + approval: "", + sessionKeyAddress: "0x", + config: testPollDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.MACI_NOT_DEPLOYED); + }); + }); +}); diff --git a/packages/coordinator/ts/deployer/__tests__/deployer.service.test.ts b/packages/coordinator/ts/deployer/__tests__/deployer.service.test.ts new file mode 100644 index 00000000..bbb59213 --- /dev/null +++ b/packages/coordinator/ts/deployer/__tests__/deployer.service.test.ts @@ -0,0 +1,526 @@ +import dotenv from "dotenv"; +import { BaseContract, zeroPadBytes } from "ethers"; +import { + InitialVoiceCreditProxy__factory as VoiceCreditProxyFactory, + ContractStorage, + EContracts, + EInitialVoiceCreditProxies, + EGatekeepers, + FreeForAllGatekeeper__factory as FreeForAllGatekeeperFactory, + EASGatekeeper__factory as EASGatekeeperFactory, + ZupassGatekeeper__factory as ZupassGatekeeperFactory, + SemaphoreGatekeeper__factory as SemaphoreGatekeeperFactory, + HatsGatekeeperSingle__factory as HatsGatekeeperSingleFactory, + GitcoinPassportGatekeeper__factory as GitcoinPassportGatekeeperFactory, + MACI__factory as MACIFactory, + Verifier__factory as VerifierFactory, +} from "maci-contracts"; +import { zeroAddress } from "viem"; + +import path from "path"; + +import { ErrorCodes, ESupportedNetworks } from "../../common"; +import { FileService } from "../../file/file.service"; +import { mockSessionKeyApproval } from "../../sessionKeys/__tests__/utils"; +import { SessionKeysService } from "../../sessionKeys/sessionKeys.service"; +import { DeployerService } from "../deployer.service"; +import { estimateExtraGasLimit } from "../utils"; + +import { testMaciDeploymentConfig, testPollDeploymentConfig } from "./utils"; + +dotenv.config(); + +describe("DeployerService", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + const chain = ESupportedNetworks.OPTIMISM_SEPOLIA; + + const fileService = new FileService(); + + const storageInstance = ContractStorage.getInstance(path.join(process.cwd(), "deployed-contracts.json")); + const sessionKeyService = new SessionKeysService(fileService); + const deployerService = new DeployerService(sessionKeyService, fileService); + const { sessionKeyAddress } = sessionKeyService.generateSessionKey(); + + describe("getVoiceCreditProxyData", () => { + test("should return the voice credit proxy data", () => { + const voiceCreditProxyData = deployerService.getVoiceCreditProxyData(EInitialVoiceCreditProxies.Constant, chain, { + amount: "50", + }); + + expect(voiceCreditProxyData).toBeDefined(); + expect(voiceCreditProxyData.alreadyDeployed).toBe(false); + expect(voiceCreditProxyData.abi).toBeDefined(); + expect(voiceCreditProxyData.bytecode).toBeDefined(); + }); + + test("should return the voice credit proxy data and that the voice credit proxy is already deployed", async () => { + await storageInstance.register({ + id: EInitialVoiceCreditProxies.Constant as unknown as EContracts, + contract: new BaseContract("0x", VoiceCreditProxyFactory.abi), + network: chain, + args: ["50"], + }); + const voiceCreditProxyData = deployerService.getVoiceCreditProxyData(EInitialVoiceCreditProxies.Constant, chain, { + amount: "50", + }); + + expect(voiceCreditProxyData).toBeDefined(); + expect(voiceCreditProxyData.alreadyDeployed).toBe(true); + expect(voiceCreditProxyData.abi).toBeDefined(); + expect(voiceCreditProxyData.bytecode).toBeDefined(); + + storageInstance.cleanup(chain); + }); + + it("should throw when the voice credits proxy is not existent", () => { + expect(() => + deployerService.getVoiceCreditProxyData("NotExistent" as unknown as EInitialVoiceCreditProxies, chain, { + amount: "50", + }), + ).toThrow(ErrorCodes.UNSUPPORTED_VOICE_CREDIT_PROXY); + }); + }); + + describe("getGatekeeperData", () => { + // we cleanup after each test so we don't have leftover saved contracts + afterEach(() => { + storageInstance.cleanup(chain); + }); + + it("should throw when the gatekeeper is not existent", () => { + expect(() => deployerService.getGatekeeperData("NotExistent" as unknown as EGatekeepers, chain)).toThrow( + ErrorCodes.UNSUPPORTED_GATEKEEPER, + ); + }); + + describe("FreeForAllGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.FreeForAll, chain); + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.FreeForAll as unknown as EContracts, + contract: new BaseContract("0x", FreeForAllGatekeeperFactory.abi), + network: chain, + args: [], + }); + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.FreeForAll, chain); + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + + describe("EASGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.EAS, chain); + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.EAS as unknown as EContracts, + contract: new BaseContract("0x", EASGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, zeroPadBytes("0x", 32), zeroAddress], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.EAS, chain, { + easAddress: zeroAddress, + schema: zeroPadBytes("0x", 32), + attester: zeroAddress, + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return that the gatekeeper is not deployed when the args are different", async () => { + await storageInstance.register({ + id: EGatekeepers.EAS as unknown as EContracts, + contract: new BaseContract("0x", EASGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, zeroPadBytes("0x", 32), zeroAddress.replace("0x0", "0x1")], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.EAS, chain, { + easAddress: zeroAddress, + schema: zeroPadBytes("0x", 32), + attester: zeroAddress, + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + + describe("ZupassGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Zupass, chain, { + signer1: zeroAddress, + signer2: zeroAddress, + eventId: "0x", + zupassVerifier: zeroAddress, + }); + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.Zupass as unknown as EContracts, + contract: new BaseContract("0x", ZupassGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, zeroAddress, "0x", zeroAddress], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Zupass, chain, { + signer1: zeroAddress, + signer2: zeroAddress, + eventId: "0x", + zupassVerifier: zeroAddress, + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return that the gatekeeper is not deployed when the args are different", async () => { + await storageInstance.register({ + id: EGatekeepers.Zupass as unknown as EContracts, + contract: new BaseContract("0x", ZupassGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, zeroAddress, "0x", zeroAddress.replace("0x0", "0x1")], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Zupass, chain, { + signer1: zeroAddress, + signer2: zeroAddress, + eventId: "0x", + zupassVerifier: zeroAddress, + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + + describe("SemaphoreGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Semaphore, chain, { + semaphoreContract: zeroAddress, + groupId: "0", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.Semaphore as unknown as EContracts, + contract: new BaseContract("0x", SemaphoreGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, "0"], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Semaphore, chain, { + semaphoreContract: zeroAddress, + groupId: "0", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return that the gatekeeper is not deployed when the args are different", async () => { + await storageInstance.register({ + id: EGatekeepers.Semaphore as unknown as EContracts, + contract: new BaseContract("0x", SemaphoreGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, "0"], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.Semaphore, chain, { + semaphoreContract: zeroAddress, + groupId: "1", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + + describe("HatsGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.HatsSingle, chain, { + hatsProtocolAddress: zeroAddress, + critrionHats: [zeroAddress], + }); + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.HatsSingle as unknown as EContracts, + contract: new BaseContract("0x", HatsGatekeeperSingleFactory.abi), + network: chain, + args: [zeroAddress, [zeroAddress]], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.HatsSingle, chain, { + hatsProtocolAddress: zeroAddress, + critrionHats: [zeroAddress], + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return that the gatekeeper is not deployed when the args are different", async () => { + await storageInstance.register({ + id: EGatekeepers.HatsSingle as unknown as EContracts, + contract: new BaseContract("0x", HatsGatekeeperSingleFactory.abi), + network: chain, + args: [zeroAddress, ["0x"]], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.HatsSingle, chain, { + hatsProtocolAddress: zeroAddress, + critrionHats: ["0x1"], + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + + describe("GitcoinPassportGatekeeper", () => { + it("should return the gatekeeper data and that the gatekeeper is not deployed", () => { + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.GitcoinPassport, chain, { + decoderAddress: zeroAddress, + passingScore: "0", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return the gatekeeper data and that the gatekeeper is already deployed", async () => { + await storageInstance.register({ + id: EGatekeepers.GitcoinPassport as unknown as EContracts, + contract: new BaseContract("0x", GitcoinPassportGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, "0"], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.GitcoinPassport, chain, { + decoderAddress: zeroAddress, + passingScore: "0", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(true); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + + it("should return that the gatekeeper is not deployed when the args are different", async () => { + await storageInstance.register({ + id: EGatekeepers.GitcoinPassport as unknown as EContracts, + contract: new BaseContract("0x", GitcoinPassportGatekeeperFactory.abi), + network: chain, + args: [zeroAddress, "0"], + }); + + const gatekeeperData = deployerService.getGatekeeperData(EGatekeepers.GitcoinPassport, chain, { + decoderAddress: zeroAddress, + passingScore: "1", + }); + + expect(gatekeeperData).toBeDefined(); + expect(gatekeeperData.alreadyDeployed).toBe(false); + expect(gatekeeperData.abi).toBeDefined(); + expect(gatekeeperData.bytecode).toBeDefined(); + }); + }); + }); + + describe("deployMaci", () => { + test("should throw when passing a non existent session key address", async () => { + await expect( + deployerService.deployMaci({ + config: testMaciDeploymentConfig, + chain, + approval: "0x", + sessionKeyAddress: "0x5", + }), + ).rejects.toThrow(ErrorCodes.SESSION_KEY_NOT_FOUND); + }); + + test("should throw when the approval is not valid", async () => { + await expect( + deployerService.deployMaci({ + config: testMaciDeploymentConfig, + chain, + approval: "0x", + sessionKeyAddress, + }), + ).rejects.toThrow(ErrorCodes.INVALID_APPROVAL); + }); + + test("should deploy all new contracts", async () => { + const approval = await mockSessionKeyApproval(sessionKeyAddress); + + const mockDeployMaci = jest.fn().mockResolvedValue(zeroAddress); + jest.spyOn(DeployerService.prototype, "deployMaci").mockImplementation(mockDeployMaci); + + const maciAddress = await deployerService.deployMaci({ + config: testMaciDeploymentConfig, + chain, + approval, + sessionKeyAddress, + }); + + expect(maciAddress).toBe(zeroAddress); + }); + }); + + describe("deployPoll", () => { + afterEach(() => { + storageInstance.cleanup(chain); + }); + + test("should throw when there is no maci contract deployed", async () => { + await expect( + deployerService.deployPoll({ + approval: "", + sessionKeyAddress: "0x", + chain, + config: testPollDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.MACI_NOT_DEPLOYED); + }); + + test("should throw when there is no maci contract deployed to this specific chain", async () => { + await storageInstance.register({ + id: EContracts.MACI, + contract: new BaseContract("0x", MACIFactory.abi), + network: ESupportedNetworks.ARBITRUM_ONE, + args: [], + }); + + await expect( + deployerService.deployPoll({ + approval: "", + sessionKeyAddress: "0x", + chain, + config: testPollDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.MACI_NOT_DEPLOYED); + }); + + it("should throw when there is no verifier deployed", async () => { + await storageInstance.register({ + id: EContracts.MACI, + contract: new BaseContract("0x", MACIFactory.abi), + network: chain, + args: [], + }); + + await expect( + deployerService.deployPoll({ + approval: "", + sessionKeyAddress: "0x", + chain, + config: testPollDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.VERIFIER_NOT_DEPLOYED); + }); + + it("should throw when there is no vk registry deployed", async () => { + await storageInstance.register({ + id: EContracts.MACI, + contract: new BaseContract("0x", MACIFactory.abi), + network: chain, + args: [], + }); + + await storageInstance.register({ + id: EContracts.Verifier, + contract: new BaseContract("0x", VerifierFactory.abi), + network: chain, + args: [], + }); + + await expect( + deployerService.deployPoll({ + approval: "", + sessionKeyAddress: "0x", + chain, + config: testPollDeploymentConfig, + }), + ).rejects.toThrow(ErrorCodes.VK_REGISTRY_NOT_DEPLOYED); + }); + + test("should deploy a poll", async () => { + const approval = await mockSessionKeyApproval(sessionKeyAddress); + + const mockDeployPoll = jest.fn().mockResolvedValue("0"); + jest.spyOn(DeployerService.prototype, "deployPoll").mockImplementation(mockDeployPoll); + + const pollId = await deployerService.deployPoll({ + config: testPollDeploymentConfig, + chain, + approval, + sessionKeyAddress, + }); + + expect(pollId).toBe("0"); + }); + }); + + describe("estimateExtraGasLimit", () => { + it("should return the extra gas limit", () => { + const extraGasLimit = estimateExtraGasLimit(100n); + expect(extraGasLimit.toString()).toBe("5"); + }); + }); +}); diff --git a/packages/coordinator/ts/deployer/__tests__/utils.ts b/packages/coordinator/ts/deployer/__tests__/utils.ts new file mode 100644 index 00000000..d478257e --- /dev/null +++ b/packages/coordinator/ts/deployer/__tests__/utils.ts @@ -0,0 +1,45 @@ +import { EGatekeepers, EInitialVoiceCreditProxies } from "maci-contracts"; +import { Keypair } from "maci-domainobjs"; + +import { IDeployMaciConfig, IDeployPollConfig } from "../types"; + +/** + * MACI deployment configuration for testing + */ +export const testMaciDeploymentConfig: IDeployMaciConfig = { + gatekeeper: { + type: EGatekeepers.FreeForAll, + }, + initialVoiceCreditsProxy: { + type: EInitialVoiceCreditProxies.Constant, + args: { + amount: "100", + }, + }, + MACI: { + gatekeeper: EGatekeepers.FreeForAll, + stateTreeDepth: 10, + }, + VkRegistry: { + args: { + stateTreeDepth: 10n, + messageTreeDepth: 2n, + voteOptionTreeDepth: 2n, + messageBatchDepth: 1n, + intStateTreeDepth: 1n, + }, + }, +}; + +/** + * Poll deployment configuration for testing + */ +export const testPollDeploymentConfig: IDeployPollConfig = { + pollDuration: 100, + useQuadraticVoting: false, + coordinatorPubkey: new Keypair().pubKey.serialize(), + intStateTreeDepth: 1, + messageTreeDepth: 2, + voteOptionTreeDepth: 2, + messageTreeSubDepth: 1, +}; diff --git a/packages/coordinator/ts/deployer/constants.ts b/packages/coordinator/ts/deployer/constants.ts new file mode 100644 index 00000000..86475f63 --- /dev/null +++ b/packages/coordinator/ts/deployer/constants.ts @@ -0,0 +1,14 @@ +/** + * The maximum gas limit for a user operation + */ +export const MAX_GAS_LIMIT = 28000000n; + +/** + * The divisor for the gas limit + */ +export const DIVISOR = 100n; + +/** + * The extra gas limit percentage + */ +export const EXTRA_GAS_LIMIT_PERCENTAGE = 5n; diff --git a/packages/coordinator/ts/deployer/deployer.controller.ts b/packages/coordinator/ts/deployer/deployer.controller.ts new file mode 100644 index 00000000..030ed449 --- /dev/null +++ b/packages/coordinator/ts/deployer/deployer.controller.ts @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/no-shadow */ +import { Body, Controller, HttpException, HttpStatus, Logger, Post, UseGuards } from "@nestjs/common"; +import { ApiBearerAuth, ApiBody, ApiResponse, ApiTags } from "@nestjs/swagger"; + +import { AccountSignatureGuard } from "../auth/AccountSignatureGuard.service"; + +import { DeployerService } from "./deployer.service"; +import { DeployerServiceDeployMaciDto, DeployerServiceDeployPollDto } from "./dto"; + +@ApiTags("v1/deploy") +@ApiBearerAuth() +@Controller("v1/deploy") +@UseGuards(AccountSignatureGuard) +export class DeployerController { + /** + * Logger + */ + private readonly logger = new Logger(DeployerController.name); + + /** + * Initialize DeployerController + * + * @param deployerService - deployer service + */ + constructor(private readonly deployerService: DeployerService) {} + + /** + * Deploy MACI contracts api method + * + * @param args - deploy maci dto + * @returns maci contract address + */ + @ApiBody({ type: DeployerServiceDeployMaciDto }) + @ApiResponse({ status: HttpStatus.CREATED, description: "The MACI contracts were successfully deployed" }) + @ApiResponse({ status: HttpStatus.FORBIDDEN, description: "Forbidden" }) + @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: "BadRequest" }) + @Post("maci") + async deployMACIContracts(@Body() args: DeployerServiceDeployMaciDto): Promise { + return this.deployerService.deployMaci(args).catch((error: Error) => { + this.logger.error(`Error:`, error); + throw new HttpException(error.message, HttpStatus.BAD_REQUEST); + }); + } + + /** + * Deploy a poll + * + * @param args - deploy poll dto + * @returns the poll id + */ + @ApiBody({ type: DeployerServiceDeployPollDto }) + @ApiResponse({ status: HttpStatus.CREATED, description: "The Poll was successfully deployed" }) + @ApiResponse({ status: HttpStatus.FORBIDDEN, description: "Forbidden" }) + @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: "BadRequest" }) + @Post("poll") + async deployPoll(@Body() args: DeployerServiceDeployPollDto): Promise { + return this.deployerService.deployPoll(args).catch((error: Error) => { + this.logger.error(`Error:`, error); + throw new HttpException(error.message, HttpStatus.BAD_REQUEST); + }); + } +} diff --git a/packages/coordinator/ts/deployer/deployer.module.ts b/packages/coordinator/ts/deployer/deployer.module.ts new file mode 100644 index 00000000..95f95ce8 --- /dev/null +++ b/packages/coordinator/ts/deployer/deployer.module.ts @@ -0,0 +1,15 @@ +import { Module } from "@nestjs/common"; + +import { CryptoModule } from "../crypto/crypto.module"; +import { FileModule } from "../file/file.module"; +import { SessionKeysModule } from "../sessionKeys/sessionKeys.module"; + +import { DeployerController } from "./deployer.controller"; +import { DeployerService } from "./deployer.service"; + +@Module({ + imports: [FileModule, CryptoModule, SessionKeysModule], + controllers: [DeployerController], + providers: [DeployerService], +}) +export class DeployerModule {} diff --git a/packages/coordinator/ts/deployer/deployer.service.ts b/packages/coordinator/ts/deployer/deployer.service.ts new file mode 100644 index 00000000..c58efacd --- /dev/null +++ b/packages/coordinator/ts/deployer/deployer.service.ts @@ -0,0 +1,936 @@ +import { Injectable, Logger } from "@nestjs/common"; +import { KernelAccountClient, KernelSmartAccount } from "@zerodev/sdk"; +import { BaseContract, InterfaceAbi } from "ethers"; +import { extractVk } from "maci-circuits"; +import { + AccQueueQuinaryMaci__factory as AccQueueQuinaryMaciFactory, + ConstantInitialVoiceCreditProxy__factory as ConstantInitialVoiceCreditProxyFactory, + ContractStorage, + EGatekeepers, + FreeForAllGatekeeper__factory as FreeForAllGatekeeperFactory, + EASGatekeeper__factory as EASGatekeeperFactory, + ZupassGatekeeper__factory as ZupassGatekeeperFactory, + HatsGatekeeperSingle__factory as HatsGatekeeperSingleFactory, + SemaphoreGatekeeper__factory as SemaphoreGatekeeperFactory, + GitcoinPassportGatekeeper__factory as GitcoinPassportGatekeeperFactory, + Verifier__factory as VerifierFactory, + PoseidonT3__factory as PoseidonT3Factory, + PoseidonT4__factory as PoseidonT4Factory, + PoseidonT5__factory as PoseidonT5Factory, + PoseidonT6__factory as PoseidonT6Factory, + VkRegistry__factory as VkRegistryFactory, + TallyFactory__factory as TallyFactoryFactory, + PollFactory__factory as PollFactoryFactory, + MessageProcessorFactory__factory as MessageProcessorFactoryFactory, + MessageProcessor__factory as MessageProcessorFactory, + Tally__factory as TallyFactory, + Poll__factory as PollFactory, + MACI__factory as MACIFactory, + EContracts, + EInitialVoiceCreditProxies, + genEmptyBallotRoots, + EMode, + IVerifyingKeyStruct, +} from "maci-contracts"; +import { IVkObjectParams, PubKey, VerifyingKey } from "maci-domainobjs"; +import { BundlerClient } from "permissionless"; +import { ENTRYPOINT_ADDRESS_V07_TYPE } from "permissionless/types"; +import { Abi, Chain, encodeFunctionData, HttpTransport, PublicClient, Transport, type Hex } from "viem"; + +import path from "path"; + +import { ErrorCodes, ESupportedNetworks, MESSAGE_TREE_ARITY } from "../common"; +import { getBundlerClient, getDeployedContractAddress, getPublicClient } from "../common/accountAbstraction"; +import { FileService } from "../file/file.service"; +import { SessionKeysService } from "../sessionKeys/sessionKeys.service"; +import { KernelClient } from "../sessionKeys/types"; + +import { MAX_GAS_LIMIT } from "./constants"; +import { + IContractData, + IDeployMaciArgs, + IDeployPollArgs, + IEASGatekeeperArgs, + IGatekeeperArgs, + IGitcoinPassportGatekeeperArgs, + IHatsGatekeeperArgs, + IInitialVoiceCreditProxyArgs, + ISemaphoreGatekeeperArgs, + IZupassGatekeeperArgs, +} from "./types"; +import { estimateExtraGasLimit } from "./utils"; + +/** + * DeployerService is responsible for deploying contracts. + */ +@Injectable() +export class DeployerService { + /** + * Logger + */ + private readonly logger = new Logger(DeployerService.name); + + /** + * Contract storage instance + */ + private readonly storage: ContractStorage; + + /** + * Create a new instance of DeployerService + * + * @param fileService - file service + */ + constructor( + private readonly sessionKeysService: SessionKeysService, + private readonly fileService: FileService, + ) { + this.logger = new Logger(DeployerService.name); + this.storage = ContractStorage.getInstance(path.join(process.cwd(), "deployed-contracts.json")); + } + + /** + * Get the gatekeeper abi and bytecode based on the gatekeeper type + * and also check if there is already an instance deployed + * + * @param gatekeeperType - the gatekeeper type + * @param network - the network + * @param args - the gatekeeper args + * @returns - the gatekeeper abi and bytecode + */ + getGatekeeperData(gatekeeperType: EGatekeepers, network: ESupportedNetworks, args?: IGatekeeperArgs): IContractData { + let address: string | undefined; + let storedArgs: string[] | undefined; + let isAlreadyDeployed: boolean; + + // based on the gatekeeper type, we need to deploy the correct gatekeeper + switch (gatekeeperType) { + case EGatekeepers.FreeForAll: + address = this.storage.getAddress(gatekeeperType as unknown as EContracts, network); + return { + abi: FreeForAllGatekeeperFactory.abi, + bytecode: FreeForAllGatekeeperFactory.bytecode, + alreadyDeployed: !!address, + }; + case EGatekeepers.EAS: + storedArgs = this.storage.getContractArgs(gatekeeperType as unknown as EContracts, network); + isAlreadyDeployed = + !!storedArgs && + storedArgs.length === 3 && + storedArgs[0] === (args as IEASGatekeeperArgs).easAddress && + storedArgs[1] === (args as IEASGatekeeperArgs).schema && + storedArgs[2] === (args as IEASGatekeeperArgs).attester; + return { + abi: EASGatekeeperFactory.abi, + bytecode: EASGatekeeperFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + case EGatekeepers.Zupass: + storedArgs = this.storage.getContractArgs(gatekeeperType as unknown as EContracts, network); + isAlreadyDeployed = + !!storedArgs && + storedArgs.length === 4 && + storedArgs[0] === (args as IZupassGatekeeperArgs).signer1 && + storedArgs[1] === (args as IZupassGatekeeperArgs).signer2 && + storedArgs[2] === (args as IZupassGatekeeperArgs).eventId && + storedArgs[3] === (args as IZupassGatekeeperArgs).zupassVerifier; + return { + abi: ZupassGatekeeperFactory.abi, + bytecode: ZupassGatekeeperFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + case EGatekeepers.HatsSingle: + storedArgs = this.storage.getContractArgs(gatekeeperType as unknown as EContracts, network); + isAlreadyDeployed = + !!storedArgs && + storedArgs.length === 2 && + storedArgs[0] === (args as IHatsGatekeeperArgs).hatsProtocolAddress && + JSON.stringify(storedArgs[1]) === JSON.stringify((args as IHatsGatekeeperArgs).critrionHats); + return { + abi: HatsGatekeeperSingleFactory.abi, + bytecode: HatsGatekeeperSingleFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + case EGatekeepers.Semaphore: + storedArgs = this.storage.getContractArgs(gatekeeperType as unknown as EContracts, network); + isAlreadyDeployed = + !!storedArgs && + storedArgs.length === 2 && + storedArgs[0] === (args as ISemaphoreGatekeeperArgs).semaphoreContract && + storedArgs[1] === (args as ISemaphoreGatekeeperArgs).groupId; + return { + abi: SemaphoreGatekeeperFactory.abi, + bytecode: SemaphoreGatekeeperFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + case EGatekeepers.GitcoinPassport: + storedArgs = this.storage.getContractArgs(gatekeeperType as unknown as EContracts, network); + isAlreadyDeployed = + !!storedArgs && + storedArgs.length === 2 && + storedArgs[0] === (args as IGitcoinPassportGatekeeperArgs).decoderAddress && + storedArgs[1] === (args as IGitcoinPassportGatekeeperArgs).passingScore; + return { + abi: GitcoinPassportGatekeeperFactory.abi, + bytecode: GitcoinPassportGatekeeperFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + default: + throw new Error(ErrorCodes.UNSUPPORTED_GATEKEEPER); + } + } + + /** + * Get the voice credit proxy abi and bytecode based on the voice credit proxy type + * and also check if there is already an instance deployed + * + * @param voiceCreditProxyType - the voice credit proxy type + * @param network - the network + * @param args - the voice credit proxy args + * @returns - the voice credit proxy abi and bytecode + */ + getVoiceCreditProxyData( + voiceCreditProxyType: EInitialVoiceCreditProxies, + network: ESupportedNetworks, + args: IInitialVoiceCreditProxyArgs, + ): IContractData { + let storedArgs: string[] | undefined; + let isAlreadyDeployed: boolean; + + switch (voiceCreditProxyType) { + case EInitialVoiceCreditProxies.Constant: + storedArgs = this.storage.getContractArgs(voiceCreditProxyType as unknown as EContracts, network); + isAlreadyDeployed = !!storedArgs && storedArgs[0] === args.amount; + + return { + abi: ConstantInitialVoiceCreditProxyFactory.abi, + bytecode: ConstantInitialVoiceCreditProxyFactory.bytecode, + alreadyDeployed: isAlreadyDeployed, + }; + default: + throw new Error(ErrorCodes.UNSUPPORTED_VOICE_CREDIT_PROXY); + } + } + + /** + * Deploy a contract and get the address + * @param kernelClient - the kernel client + * @param abi - the abi + * @param bytecode - the bytecode + * @param args - the args + * @param publicClient - the public client + * @returns - the address + */ + async deployAndGetAddress( + kernelClient: KernelAccountClient< + ENTRYPOINT_ADDRESS_V07_TYPE, + Transport, + Chain, + KernelSmartAccount + >, + abi: Abi, + bytecode: Hex, + args: unknown[], + bundlerClient: BundlerClient, + publicClient: PublicClient, + ): Promise { + const deployCallData = await kernelClient.account.encodeDeployCallData({ + abi, + args, + bytecode, + }); + + const gasPrice = await kernelClient.getUserOperationGasPrice(); + + const opEstimate = await kernelClient.prepareUserOperationRequest({ + userOperation: { + callData: deployCallData, + sender: kernelClient.account.address, + maxFeePerGas: gasPrice.maxFeePerGas, + maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas, + }, + }); + + const callGasLimitMultiplier = estimateExtraGasLimit(opEstimate.callGasLimit); + + const tx = await kernelClient.sendUserOperation({ + userOperation: { + callData: deployCallData, + sender: kernelClient.account.address, + maxFeePerGas: gasPrice.maxFeePerGas, + maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas, + callGasLimit: + opEstimate.callGasLimit + callGasLimitMultiplier < MAX_GAS_LIMIT + ? opEstimate.callGasLimit + callGasLimitMultiplier + : MAX_GAS_LIMIT, + }, + }); + + const receipt = await bundlerClient.waitForUserOperationReceipt({ + hash: tx, + }); + + const txReceipt = await publicClient.getTransactionReceipt({ + hash: receipt.receipt.transactionHash, + }); + + return getDeployedContractAddress(txReceipt); + } + + /** + * Deploy a contract and store the address + * + * @param contract - the contract to deploy + * @param args - the args + * @param abi - the abi + * @param bytecode - the bytecode + * @param kernelClient - the kernel client + * @param publicClient - the public client + * @param chain - the chain + * @returns - the address of the deployed contract + */ + async deployAndStore( + contract: EContracts, + args: unknown[], + abi: Abi, + bytecode: Hex, + kernelClient: KernelClient, + bundlerClient: BundlerClient, + publicClient: PublicClient, + chain: ESupportedNetworks, + ): Promise { + let address = this.storage.getAddress(contract, chain); + + if (!address) { + address = await this.deployAndGetAddress(kernelClient, abi, bytecode, args, bundlerClient, publicClient); + + if (!address) { + this.logger.error(`Failed to deploy contract: ${contract}`); + throw new Error(`${ErrorCodes.FAILED_TO_DEPLOY_CONTRACT} ${contract}`); + } + + await this.storage.register({ + id: contract, + contract: new BaseContract(address, abi as unknown as InterfaceAbi), + args: args.map((arg) => String(arg)), + network: chain, + }); + } + + return address; + } + + /** + * Deploy MACI contracts + * + * @param args - deploy maci arguments + * @param options - ws hooks + * @returns - deployed maci contract + * @returns the address of the deployed maci contract + */ + async deployMaci({ approval, sessionKeyAddress, chain, config }: IDeployMaciArgs): Promise { + const publicClient = getPublicClient(chain); + const bundlerClient = getBundlerClient(chain); + + const kernelClient = await this.sessionKeysService.generateClientFromSessionKey(sessionKeyAddress, approval, chain); + + let initialVoiceCreditProxyAddress = this.storage.getAddress( + config.initialVoiceCreditsProxy.type as unknown as EContracts, + chain, + ); + + const initialVoiceCreditProxyData = this.getVoiceCreditProxyData( + config.initialVoiceCreditsProxy.type, + chain, + config.initialVoiceCreditsProxy.args, + ); + + // if the initial voice credit proxy is not already deployed, we need to deploy it + if (!initialVoiceCreditProxyData.alreadyDeployed) { + initialVoiceCreditProxyAddress = await this.deployAndGetAddress( + kernelClient, + initialVoiceCreditProxyData.abi, + initialVoiceCreditProxyData.bytecode, + Object.values(config.initialVoiceCreditsProxy.args), + bundlerClient, + publicClient, + ); + + if (!initialVoiceCreditProxyAddress) { + this.logger.error(`Failed to deploy voice credit proxy: ${config.initialVoiceCreditsProxy.type}`); + throw new Error(`${ErrorCodes.FAILED_TO_DEPLOY_CONTRACT} ${config.initialVoiceCreditsProxy.type}`); + } + + await this.storage.register({ + id: config.initialVoiceCreditsProxy.type as unknown as EContracts, + contract: new BaseContract( + initialVoiceCreditProxyAddress, + initialVoiceCreditProxyData.abi as unknown as InterfaceAbi, + ), + args: Object.values(config.initialVoiceCreditsProxy.args), + network: chain, + }); + } + + let gatekeeperAddress = this.storage.getAddress(config.gatekeeper.type as unknown as EContracts, chain); + const gatekeeperData = this.getGatekeeperData(config.gatekeeper.type, chain, config.gatekeeper.args); + + // if the gatekeeper is not already deployed, we need to deploy it + if (!gatekeeperData.alreadyDeployed) { + gatekeeperAddress = await this.deployAndGetAddress( + kernelClient, + gatekeeperData.abi, + gatekeeperData.bytecode, + config.gatekeeper.args ? Object.values(config.gatekeeper.args) : [], + bundlerClient, + publicClient, + ); + + // if the gatekeeper address is not found, we need to throw an error + if (!gatekeeperAddress) { + this.logger.error(`Failed to deploy gatekeeper: ${config.gatekeeper.type}`); + throw new Error(`${ErrorCodes.FAILED_TO_DEPLOY_CONTRACT} ${config.gatekeeper.type}`); + } + + // store the gatekeeper address in the storage + await this.storage.register({ + id: config.gatekeeper.type as unknown as EContracts, + contract: new BaseContract(gatekeeperAddress, gatekeeperData.abi as InterfaceAbi), + args: config.gatekeeper.args ? Object.values(config.gatekeeper.args) : [], + network: chain, + }); + } + + // deploy all maci contracts + + // 1. verifier + await this.deployAndStore( + EContracts.Verifier, + [], + VerifierFactory.abi, + VerifierFactory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + // 2. poseidon + const poseidonT3Address = await this.deployAndStore( + EContracts.PoseidonT3, + [], + PoseidonT3Factory.abi, + PoseidonT3Factory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + const poseidonT4Address = await this.deployAndStore( + EContracts.PoseidonT4, + [], + PoseidonT4Factory.abi, + PoseidonT4Factory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + const poseidonT5Address = await this.deployAndStore( + EContracts.PoseidonT5, + [], + PoseidonT5Factory.abi, + PoseidonT5Factory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + const poseidonT6Address = await this.deployAndStore( + EContracts.PoseidonT6, + [], + PoseidonT6Factory.abi, + PoseidonT6Factory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + // 3. factories + const pollFactoryAddress = await this.deployAndStore( + EContracts.PollFactory, + [], + PollFactoryFactory.abi as unknown as Abi, + PollFactoryFactory.linkBytecode({ + "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonT3Address, + "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonT4Address, + "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonT5Address, + "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonT6Address, + }) as Hex, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + const tallyFactoryAddress = await this.deployAndStore( + EContracts.TallyFactory, + [], + TallyFactoryFactory.abi as unknown as Abi, + TallyFactoryFactory.linkBytecode({ + "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonT3Address, + "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonT4Address, + "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonT5Address, + "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonT6Address, + }) as Hex, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + const messageProcessorFactoryAddress = await this.deployAndStore( + EContracts.MessageProcessorFactory, + [], + MessageProcessorFactoryFactory.abi, + MessageProcessorFactoryFactory.linkBytecode({ + "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonT3Address, + "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonT4Address, + "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonT5Address, + "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonT6Address, + }) as Hex, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + // 4. VkRegistry + const vkRegistryAddress = await this.deployAndStore( + EContracts.VkRegistry, + [], + VkRegistryFactory.abi, + VkRegistryFactory.bytecode, + kernelClient, + bundlerClient, + publicClient, + chain, + ); + + try { + const processMessagesZkeyPathQv = this.fileService.getZkeyFilePaths( + process.env.COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME!, + true, + ); + const tallyVotesZkeyPathQv = this.fileService.getZkeyFilePaths(process.env.COORDINATOR_TALLY_ZKEY_NAME!, true); + const processMessagesZkeyPathNonQv = this.fileService.getZkeyFilePaths( + process.env.COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME!, + false, + ); + const tallyVotesZkeyPathNonQv = this.fileService.getZkeyFilePaths( + process.env.COORDINATOR_TALLY_ZKEY_NAME!, + false, + ); + + const [qvProcessVk, qvTallyVk, nonQvProcessVk, nonQvTallyVk] = await Promise.all([ + extractVk(processMessagesZkeyPathQv.zkey), + extractVk(tallyVotesZkeyPathQv.zkey), + extractVk(processMessagesZkeyPathNonQv.zkey), + extractVk(tallyVotesZkeyPathNonQv.zkey), + ]).then((vks) => + vks.map( + (vk: IVkObjectParams | "" | undefined) => + vk && (VerifyingKey.fromObj(vk).asContractParam() as IVerifyingKeyStruct), + ), + ); + + const processZkeys = [qvProcessVk, nonQvProcessVk].filter(Boolean) as IVerifyingKeyStruct[]; + const tallyZkeys = [qvTallyVk, nonQvTallyVk].filter(Boolean) as IVerifyingKeyStruct[]; + + // check if the keys are already set + const isProcessVkSet = await publicClient.readContract({ + address: vkRegistryAddress as Hex, + abi: VkRegistryFactory.abi, + functionName: "hasProcessVk", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.messageTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + MESSAGE_TREE_ARITY ** config.VkRegistry.args.messageBatchDepth, + EMode.QV, + ], + }); + + const isProcessNonQvVkSet = await publicClient.readContract({ + address: vkRegistryAddress as Hex, + abi: VkRegistryFactory.abi, + functionName: "hasProcessVk", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.messageTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + MESSAGE_TREE_ARITY ** config.VkRegistry.args.messageBatchDepth, + EMode.NON_QV, + ], + }); + + const isTallyVkSet = await publicClient.readContract({ + address: vkRegistryAddress as Hex, + abi: VkRegistryFactory.abi, + functionName: "hasTallyVk", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.intStateTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + EMode.QV, + ], + }); + + const isTallyNonQvVkSet = await publicClient.readContract({ + address: vkRegistryAddress as Hex, + abi: VkRegistryFactory.abi, + functionName: "hasTallyVk", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.intStateTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + EMode.QV, + ], + }); + + if (isProcessVkSet && isProcessNonQvVkSet && isTallyVkSet && isTallyNonQvVkSet) { + this.logger.debug("Verifying keys are already set on the vk registry"); + } else { + const gasEstimates = await kernelClient.getUserOperationGasPrice(); + const opEstimate = await kernelClient.prepareUserOperationRequest({ + userOperation: { + sender: kernelClient.account.address, + maxFeePerGas: gasEstimates.maxFeePerGas, + maxPriorityFeePerGas: gasEstimates.maxPriorityFeePerGas, + callData: await kernelClient.account.encodeCallData({ + to: vkRegistryAddress as Hex, + value: 0n, + data: encodeFunctionData({ + abi: VkRegistryFactory.abi, + functionName: "setVerifyingKeysBatch", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.intStateTreeDepth, + config.VkRegistry.args.messageTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + MESSAGE_TREE_ARITY ** config.VkRegistry.args.messageBatchDepth, + [EMode.QV, EMode.NON_QV], + // @ts-expect-error - the abi has a more complex type for the processZkeys and tallyZkeys + processZkeys, + // @ts-expect-error - the abi has a more complex type for the processZkeys and tallyZkeys + tallyZkeys, + ], + }), + }), + }, + }); + // set vKeys on the vk registry + const callGasLimitMultiplier = estimateExtraGasLimit(opEstimate.callGasLimit); + + const userOpHashVkRegistry = await kernelClient.sendUserOperation({ + userOperation: { + callGasLimit: + opEstimate.callGasLimit + callGasLimitMultiplier < MAX_GAS_LIMIT + ? opEstimate.callGasLimit + callGasLimitMultiplier + : MAX_GAS_LIMIT, + sender: kernelClient.account.address, + maxFeePerGas: gasEstimates.maxFeePerGas, + maxPriorityFeePerGas: gasEstimates.maxPriorityFeePerGas, + callData: await kernelClient.account.encodeCallData({ + to: vkRegistryAddress as Hex, + value: 0n, + data: encodeFunctionData({ + abi: VkRegistryFactory.abi, + functionName: "setVerifyingKeysBatch", + args: [ + config.VkRegistry.args.stateTreeDepth, + config.VkRegistry.args.intStateTreeDepth, + config.VkRegistry.args.messageTreeDepth, + config.VkRegistry.args.voteOptionTreeDepth, + MESSAGE_TREE_ARITY ** config.VkRegistry.args.messageBatchDepth, + [EMode.QV, EMode.NON_QV], + // @ts-expect-error - the abi has a more complex type for the processZkeys and tallyZkeys + processZkeys, + // @ts-expect-error - the abi has a more complex type for the processZkeys and tallyZkeys + tallyZkeys, + ], + }), + }), + }, + }); + + const receiptVkRegistry = await bundlerClient.waitForUserOperationReceipt({ + hash: userOpHashVkRegistry, + }); + + if (!receiptVkRegistry.success) { + throw new Error(ErrorCodes.FAILED_TO_SET_VERIFYING_KEYS_ON_VK_REGISTRY); + } + } + } catch (error) { + this.logger.error("Failed to set verifying keys on vk registry: ", error); + } + + // 5. maci (here we don't check whether one is already deployed, we just deploy it) + const emptyBallotRoots = genEmptyBallotRoots(config.MACI.stateTreeDepth); + + const maciAddress = await this.deployAndGetAddress( + kernelClient, + MACIFactory.abi, + MACIFactory.linkBytecode({ + "contracts/crypto/PoseidonT3.sol:PoseidonT3": poseidonT3Address, + "contracts/crypto/PoseidonT4.sol:PoseidonT4": poseidonT4Address, + "contracts/crypto/PoseidonT5.sol:PoseidonT5": poseidonT5Address, + "contracts/crypto/PoseidonT6.sol:PoseidonT6": poseidonT6Address, + }) as Hex, + [ + pollFactoryAddress, + messageProcessorFactoryAddress, + tallyFactoryAddress, + gatekeeperAddress, + initialVoiceCreditProxyAddress, + config.MACI.stateTreeDepth, + emptyBallotRoots, + ], + bundlerClient, + publicClient, + ); + + if (!maciAddress) { + throw new Error(`${ErrorCodes.FAILED_TO_DEPLOY_CONTRACT} - ${EContracts.MACI}`); + } + + await this.storage.register({ + id: EContracts.MACI, + contract: new BaseContract(maciAddress, MACIFactory.abi as unknown as InterfaceAbi), + args: [ + pollFactoryAddress, + messageProcessorFactoryAddress, + tallyFactoryAddress, + gatekeeperAddress, + initialVoiceCreditProxyAddress, + config.MACI.stateTreeDepth, + emptyBallotRoots.map((root) => root.toString()), + ], + network: chain, + }); + + // set the gate on the gatekeeper + const userOpHash = await kernelClient.sendUserOperation({ + userOperation: { + callData: await kernelClient.account.encodeCallData({ + to: gatekeeperAddress! as Hex, + value: 0n, + data: encodeFunctionData({ + abi: gatekeeperData.abi, + functionName: "setMaciInstance", + args: [maciAddress], + }), + }), + }, + account: kernelClient.account, + }); + + const receipt = await bundlerClient.waitForUserOperationReceipt({ + hash: userOpHash, + }); + + if (!receipt.success) { + throw new Error(ErrorCodes.FAILED_TO_SET_MACI_INSTANCE_ON_GATEKEEPER); + } + + return maciAddress; + } + + /** + * Deploy a poll + * + * @param args - deploy poll dto + * @returns poll id + */ + async deployPoll({ approval, sessionKeyAddress, chain, config }: IDeployPollArgs): Promise { + // check if there is a maci contract deployed on this chain + const maciAddress = this.storage.getAddress(EContracts.MACI, chain); + if (!maciAddress) { + throw new Error(ErrorCodes.MACI_NOT_DEPLOYED); + } + + // check if there is a verifier deployed on this chain + const verifierAddress = this.storage.getAddress(EContracts.Verifier, chain); + if (!verifierAddress) { + throw new Error(ErrorCodes.VERIFIER_NOT_DEPLOYED); + } + + // check if there is a vk registry deployed on this chain + const vkRegistryAddress = this.storage.getAddress(EContracts.VkRegistry, chain); + if (!vkRegistryAddress) { + throw new Error(ErrorCodes.VK_REGISTRY_NOT_DEPLOYED); + } + + const mode = config.useQuadraticVoting ? EMode.QV : EMode.NON_QV; + + const kernelClient = await this.sessionKeysService.generateClientFromSessionKey(sessionKeyAddress, approval, chain); + + const publicClient = getPublicClient(chain); + const bundlerClient = getBundlerClient(chain); + + const pollId = await publicClient.readContract({ + address: maciAddress as Hex, + abi: MACIFactory.abi, + functionName: "nextPollId", + }); + + try { + const gasEstimates = await kernelClient.getUserOperationGasPrice(); + const opEstimate = await kernelClient.prepareUserOperationRequest({ + userOperation: { + sender: kernelClient.account.address, + maxFeePerGas: gasEstimates.maxFeePerGas, + maxPriorityFeePerGas: gasEstimates.maxPriorityFeePerGas, + callData: await kernelClient.account.encodeCallData({ + to: maciAddress as Hex, + value: 0n, + data: encodeFunctionData({ + abi: MACIFactory.abi, + functionName: "deployPoll", + args: [ + BigInt(config.pollDuration), + { + intStateTreeDepth: config.intStateTreeDepth, + messageTreeSubDepth: config.messageTreeSubDepth, + messageTreeDepth: config.messageTreeDepth, + voteOptionTreeDepth: config.voteOptionTreeDepth, + }, + PubKey.deserialize(config.coordinatorPubkey).asContractParam() as { x: bigint; y: bigint }, + verifierAddress as Hex, + vkRegistryAddress as Hex, + mode, + ], + }), + }), + }, + }); + + const callGasLimitMultiplier = estimateExtraGasLimit(opEstimate.callGasLimit); + + const userOpHash = await kernelClient.sendUserOperation({ + userOperation: { + sender: kernelClient.account.address, + maxFeePerGas: gasEstimates.maxFeePerGas, + maxPriorityFeePerGas: gasEstimates.maxPriorityFeePerGas, + callGasLimit: + opEstimate.callGasLimit + callGasLimitMultiplier < MAX_GAS_LIMIT + ? opEstimate.callGasLimit + callGasLimitMultiplier + : MAX_GAS_LIMIT, + callData: await kernelClient.account.encodeCallData({ + to: maciAddress as Hex, + value: 0n, + data: encodeFunctionData({ + abi: MACIFactory.abi, + functionName: "deployPoll", + args: [ + BigInt(config.pollDuration), + { + intStateTreeDepth: config.intStateTreeDepth, + messageTreeSubDepth: config.messageTreeSubDepth, + messageTreeDepth: config.messageTreeDepth, + voteOptionTreeDepth: config.voteOptionTreeDepth, + }, + PubKey.deserialize(config.coordinatorPubkey).asContractParam() as { x: bigint; y: bigint }, + verifierAddress as Hex, + vkRegistryAddress as Hex, + mode, + ], + }), + }), + }, + }); + + const receipt = await bundlerClient.waitForUserOperationReceipt({ + hash: userOpHash, + }); + + if (!receipt.success) { + throw new Error(`${ErrorCodes.FAILED_TO_DEPLOY_CONTRACT} - ${EContracts.Poll}`); + } + } catch (error) { + this.logger.error("error deploying poll", error); + throw new Error(ErrorCodes.FAILED_TO_DEPLOY_POLL); + } + + // get the addresses so we can store this information + const pollAddresses = await publicClient.readContract({ + address: maciAddress as Hex, + abi: MACIFactory.abi, + functionName: "getPoll", + args: [pollId], + }); + + // read the emptyBallotRoot + const emptyBallotRoot = await publicClient.readContract({ + address: pollAddresses.poll, + abi: PollFactory.abi, + functionName: "emptyBallotRoot", + }); + + const extContracts = await publicClient.readContract({ + address: pollAddresses.poll, + abi: PollFactory.abi, + functionName: "extContracts", + }); + + // store to storage + await Promise.all([ + this.storage.register({ + id: EContracts.Poll, + key: `poll-${pollId}`, + contract: new BaseContract(pollAddresses.poll, PollFactory.abi as unknown as InterfaceAbi), + args: [ + config.pollDuration, + { + intStateTreeDepth: config.intStateTreeDepth, + messageTreeSubDepth: config.messageTreeSubDepth, + messageTreeDepth: config.messageTreeDepth, + voteOptionTreeDepth: config.voteOptionTreeDepth, + }, + PubKey.deserialize(config.coordinatorPubkey).asContractParam() as { x: bigint; y: bigint }, + extContracts, + emptyBallotRoot.toString(), + ], + network: chain, + }), + this.storage.register({ + id: EContracts.MessageProcessor, + key: `poll-${pollId}`, + contract: new BaseContract(pollAddresses.messageProcessor, MessageProcessorFactory.abi), + args: [verifierAddress, vkRegistryAddress, pollAddresses.poll, mode], + network: chain, + }), + this.storage.register({ + id: EContracts.Tally, + key: `poll-${pollId}`, + contract: new BaseContract(pollAddresses.tally, TallyFactory.abi), + args: [verifierAddress, vkRegistryAddress, pollAddresses.poll, pollAddresses.messageProcessor, mode], + network: chain, + }), + this.storage.register({ + id: EContracts.AccQueueQuinaryMaci, + key: `poll-${pollId}`, + name: "contracts/trees/AccQueueQuinaryMaci.sol:AccQueueQuinaryMaci", + contract: new BaseContract(extContracts[1], AccQueueQuinaryMaciFactory.abi), + args: [config.messageTreeSubDepth], + network: chain, + }), + ]); + + return pollId.toString(); + } +} diff --git a/packages/coordinator/ts/deployer/dto.ts b/packages/coordinator/ts/deployer/dto.ts new file mode 100644 index 00000000..a9daa308 --- /dev/null +++ b/packages/coordinator/ts/deployer/dto.ts @@ -0,0 +1,100 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { Transform } from "class-transformer"; +import { IsEnum, IsString } from "class-validator"; + +import type { IDeployMaciConfig, IDeployPollConfig } from "./types"; +import type { Hex } from "viem"; + +import { ESupportedNetworks } from "../common"; + +export const transformToString = ({ value }: { value: string }): string => value.toLowerCase(); + +/** + * Data transfer object for MACI contracts deployment + */ +export class DeployerServiceDeployMaciDto { + /** + * Session Key Approval string + */ + @ApiProperty({ + description: "Session Key Approval string", + type: String, + }) + @IsString() + approval!: string; + + /** + * Address of the session key + */ + @ApiProperty({ + description: "Address of the session key", + type: String, + }) + @IsString() + sessionKeyAddress!: Hex; + + /** + * Chain Name + */ + @ApiProperty({ + description: "Chain to which to deploy the contract(s)", + enum: ESupportedNetworks, + }) + @IsEnum(ESupportedNetworks) + @Transform(transformToString) + chain!: ESupportedNetworks; + + /** + * Config + */ + @ApiProperty({ + description: "Deployment configuration", + type: Object, + }) + config!: IDeployMaciConfig; +} + +/** + * Data transfer object for Poll contract deployment + */ +export class DeployerServiceDeployPollDto { + /** + * Session Key Approval string + */ + @ApiProperty({ + description: "Session Key Approval string", + type: String, + }) + @IsString() + approval!: string; + + /** + * Address of the session key + */ + @ApiProperty({ + description: "Address of the session key", + type: String, + }) + @IsString() + sessionKeyAddress!: Hex; + + /** + * Chain Name + */ + @ApiProperty({ + description: "Chain to which to deploy the contract(s)", + enum: ESupportedNetworks, + }) + @IsEnum(ESupportedNetworks) + @Transform(transformToString) + chain!: ESupportedNetworks; + + /** + * Config + */ + @ApiProperty({ + description: "Deployment configuration", + type: Object, + }) + config!: IDeployPollConfig; +} diff --git a/packages/coordinator/ts/deployer/types.ts b/packages/coordinator/ts/deployer/types.ts new file mode 100644 index 00000000..938be997 --- /dev/null +++ b/packages/coordinator/ts/deployer/types.ts @@ -0,0 +1,263 @@ +import { EGatekeepers, EInitialVoiceCreditProxies } from "maci-contracts"; + +import type { Abi, Hex } from "viem"; + +import { ESupportedNetworks } from "../common"; + +/** + * IDeployMACIArgs represents the arguments for deploying MACI + */ +export interface IDeployMaciArgs { + /** + * The address of the session key + */ + sessionKeyAddress: Hex; + /** + * The approval for the session key + */ + approval: string; + /** + * The chain name + */ + chain: ESupportedNetworks; + /** + * The configuration for deploying MACI + */ + config: IDeployMaciConfig; +} + +/** + * IDeployPollArgs represents the arguments for deploying a poll + */ +export interface IDeployPollArgs { + /** + * The address of the session key + */ + sessionKeyAddress: Hex; + /** + * The approval for the session key + */ + approval: string; + /** + * The chain name + */ + chain: ESupportedNetworks; + /** + * The configuration for deploying a poll + */ + config: IDeployPollConfig; +} + +/** + * IConstantInitialVoiceCreditProxyArgs represents the arguments for deploying a constant initial voice credit proxy + */ +export interface IConstantInitialVoiceCreditProxyArgs { + /** + * The amount of initial voice credits to deploy + */ + amount: string; +} + +/** + * IEASGatekeeperArgs represents the arguments for deploying an EAS gatekeeper + */ +export interface IEASGatekeeperArgs { + /** + * The address of the EAS contract + */ + easAddress: string; + /** + * The attestation schema to be used + */ + schema: string; + /** + * The trusted attester + */ + attester: string; +} + +/** + * IZupassGatekeeperArgs represents the arguments for deploying a Zupass gatekeeper + */ +export interface IZupassGatekeeperArgs { + /** + * The first signer + */ + signer1: string; + /** + * The second signer + */ + signer2: string; + /** + * The event ID + */ + eventId: string; + /** + * The Zupass verifier address + */ + zupassVerifier: string; +} + +/** + * IHatsGatekeeperArgs represents the arguments for deploying a Hats gatekeeper + */ +export interface IHatsGatekeeperArgs { + /** + * The hats protocol address + */ + hatsProtocolAddress: string; + /** + * The criterion hats + */ + critrionHats: string[]; +} + +/** + * ISemaphoreGatekeeperArgs represents the arguments for deploying a semaphore gatekeeper + */ +export interface ISemaphoreGatekeeperArgs { + /** + * The semaphore contract address + */ + semaphoreContract: string; + /** + * The group ID + */ + groupId: string; +} + +/** + * IGitcoinPassportGatekeeperArgs represents the arguments for deploying a gitcoin passport gatekeeper + */ +export interface IGitcoinPassportGatekeeperArgs { + /** + * The decoder address + */ + decoderAddress: string; + /** + * The passing score + */ + passingScore: string; +} + +/** + * IVkRegistryArgs represents the arguments for deploying a VkRegistry + */ +export interface IVkRegistryArgs { + /** + * The state tree depth + */ + stateTreeDepth: bigint; + /** + * The int state tree depth determines the tally batch size + */ + intStateTreeDepth: bigint; + /** + * The message tree depth + */ + messageTreeDepth: bigint; + /** + * The vote option tree depth + */ + voteOptionTreeDepth: bigint; + /** + * The message batch depth + */ + messageBatchDepth: bigint; +} + +/** + * IGatekeeperArgs represents the arguments for deploying a gatekeeper + */ +export type IGatekeeperArgs = + | IEASGatekeeperArgs + | IZupassGatekeeperArgs + | IHatsGatekeeperArgs + | ISemaphoreGatekeeperArgs + | IGitcoinPassportGatekeeperArgs; + +export type IInitialVoiceCreditProxyArgs = IConstantInitialVoiceCreditProxyArgs; +/** + * DeployMaciConfig is the configuration for deploying MACI + */ +export interface IDeployMaciConfig { + /** + * The gatekeeper configuration + */ + gatekeeper: { + type: EGatekeepers; + args?: IGatekeeperArgs; + }; + /** + * The initial voice credits proxy configuration + */ + initialVoiceCreditsProxy: { + type: EInitialVoiceCreditProxies; + args: IInitialVoiceCreditProxyArgs; + }; + /** + * The MACI configuration + */ + MACI: { + stateTreeDepth: number; + gatekeeper: EGatekeepers; + }; + /** + * The VkRegistry configuration + */ + VkRegistry: { + args: IVkRegistryArgs; + }; +} + +/** + * DeployPollConfig is the configuration for deploying a poll + */ +export interface IDeployPollConfig { + /** + * The poll duration + */ + pollDuration: number; + /** + * The coordinator pubkey + */ + coordinatorPubkey: string; + /** + * Whether to use quadratic voting + */ + useQuadraticVoting: boolean; + /** + * Determines the tally batch size + */ + intStateTreeDepth: number; + /** + * Determines the message batch size + */ + messageTreeSubDepth: number; + /** + * Message tree depth + */ + messageTreeDepth: number; + /** + * Vote option tree depth + */ + voteOptionTreeDepth: number; +} + +/** + * IContractData represents the data for a contract + */ +export interface IContractData { + /** + * The ABI of the contract + */ + abi: Abi; + /** + * The bytecode of the contract + */ + bytecode: Hex; + /** + * Whether the contract is already deployed + */ + alreadyDeployed: boolean; +} diff --git a/packages/coordinator/ts/deployer/utils.ts b/packages/coordinator/ts/deployer/utils.ts new file mode 100644 index 00000000..5c431254 --- /dev/null +++ b/packages/coordinator/ts/deployer/utils.ts @@ -0,0 +1,10 @@ +import { DIVISOR, EXTRA_GAS_LIMIT_PERCENTAGE } from "./constants"; + +/** + * Estimate the extra gas limit + * + * @param callGasLimit The gas limit of the call + * @returns The extra gas limit + */ +export const estimateExtraGasLimit = (callGasLimit: bigint): bigint => + (callGasLimit * EXTRA_GAS_LIMIT_PERCENTAGE) / DIVISOR; diff --git a/packages/coordinator/ts/sessionKeys/__tests__/sessionKeys.service.test.ts b/packages/coordinator/ts/sessionKeys/__tests__/sessionKeys.service.test.ts index 6ee18d9a..1c148c90 100644 --- a/packages/coordinator/ts/sessionKeys/__tests__/sessionKeys.service.test.ts +++ b/packages/coordinator/ts/sessionKeys/__tests__/sessionKeys.service.test.ts @@ -81,6 +81,7 @@ describe("SessionKeysService", () => { approval, ESupportedNetworks.OPTIMISM_SEPOLIA, ); + expect(mockGenerateClientFromSessionKey).toHaveBeenCalledWith( sessionKeyAddress.sessionKeyAddress, approval, diff --git a/packages/coordinator/ts/sessionKeys/sessionKeys.service.ts b/packages/coordinator/ts/sessionKeys/sessionKeys.service.ts index b3b1f51f..f6f16801 100644 --- a/packages/coordinator/ts/sessionKeys/sessionKeys.service.ts +++ b/packages/coordinator/ts/sessionKeys/sessionKeys.service.ts @@ -11,7 +11,7 @@ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import type { Chain, Hex, HttpTransport, Transport } from "viem"; import { ErrorCodes, ESupportedNetworks } from "../common"; -import { getPublicClient } from "../common/accountAbstraction"; +import { getPublicClient, getZeroDevBundlerRPCUrl } from "../common/accountAbstraction"; import { viemChain } from "../common/networks"; import { FileService } from "../file/file.service"; @@ -105,7 +105,7 @@ export class SessionKeysService { ); return createKernelAccountClient({ - bundlerTransport: http(process.env.ZERODEV_BUNDLER_RPC), + bundlerTransport: http(getZeroDevBundlerRPCUrl(chain)), entryPoint: ENTRYPOINT_ADDRESS_V07, account: sessionKeyAccount, chain: viemChain(chain), diff --git a/packages/coordinator/ts/sessionKeys/types.ts b/packages/coordinator/ts/sessionKeys/types.ts index ff4f93d7..72c95f42 100644 --- a/packages/coordinator/ts/sessionKeys/types.ts +++ b/packages/coordinator/ts/sessionKeys/types.ts @@ -1,4 +1,7 @@ -import type { Hex } from "viem"; +import { KernelAccountClient, KernelSmartAccount } from "@zerodev/sdk"; +import { ENTRYPOINT_ADDRESS_V07_TYPE } from "permissionless/types"; + +import type { Chain, Hex, HttpTransport, Transport } from "viem"; /** * Generate session key return type @@ -9,3 +12,10 @@ export interface IGenerateSessionKeyReturn { */ sessionKeyAddress: Hex; } + +export type KernelClient = KernelAccountClient< + ENTRYPOINT_ADDRESS_V07_TYPE, + Transport, + Chain, + KernelSmartAccount +>; diff --git a/packages/interface/package.json b/packages/interface/package.json index 54c568aa..3e68de5b 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -32,6 +32,11 @@ "@trpc/react-query": "11.0.0-next-beta.294", "@trpc/server": "11.0.0-next-beta.294", "@vercel/blob": "^0.19.0", + "@zerodev/ecdsa-validator": "^5.3.1", + "@zerodev/permissions": "^5.4.3", + "@zerodev/sdk": "^5.3.8", + "@zerodev/session-key": "^5.4.2", + "@zerodev/passkey-validator": "^5.4.1", "clsx": "^2.1.0", "date-fns": "^3.6.0", "dotenv": "^16.4.1", @@ -46,6 +51,7 @@ "next-themes": "^0.2.1", "node-fetch-cache": "^5.0.2", "nuqs": "^1.17.1", + "permissionless": ">=0.1.18 <=0.1.29", "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.49.3", @@ -58,7 +64,7 @@ "tailwind-merge": "^2.2.1", "tailwind-variants": "^0.1.20", "tailwindcss": "^3.4.1", - "viem": "^2.7.15", + "viem": "2.16.3", "wagmi": "^2.9.8", "zod": "3.22.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b1fac88..3fa2c74b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -236,7 +236,7 @@ importers: version: 2.3.0(g3d4wepazdznljietc42e5anoy) maci-domainobjs: specifier: ^2.0.0 - version: 2.0.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + version: 2.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) maci-subgraph: specifier: ^2.3.0 version: 2.3.0(jqbxnb2fveugzmo4mmcj7czc2y) @@ -315,7 +315,7 @@ importers: version: 1.6.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) '@hatsprotocol/sdk-v1-core': specifier: ^0.10.0 - version: 0.10.0(encoding@0.1.13)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + version: 0.10.0(encoding@0.1.13)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) '@hookform/resolvers': specifier: ^3.3.4 version: 3.9.0(react-hook-form@7.52.2(react@18.2.0)) @@ -330,7 +330,7 @@ importers: version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@rainbow-me/rainbowkit': specifier: ^2.0.1 - version: 2.1.4(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4)) + version: 2.1.4(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4)) '@semaphore-protocol/core': specifier: 4.0.3 version: 4.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -358,6 +358,21 @@ importers: '@vercel/blob': specifier: ^0.19.0 version: 0.19.0 + '@zerodev/ecdsa-validator': + specifier: ^5.3.1 + version: 5.3.1(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/passkey-validator': + specifier: ^5.4.1 + version: 5.4.1(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(@zerodev/webauthn-key@5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/permissions': + specifier: ^5.4.3 + version: 5.4.3(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(@zerodev/webauthn-key@5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/sdk': + specifier: ^5.3.8 + version: 5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/session-key': + specifier: ^5.4.2 + version: 5.4.2(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) clsx: specifier: ^2.1.0 version: 2.1.1 @@ -400,6 +415,9 @@ importers: nuqs: specifier: ^1.17.1 version: 1.17.7(next@14.2.5(@babel/core@7.25.2)(@playwright/test@1.46.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)) + permissionless: + specifier: '>=0.1.18 <=0.1.29' + version: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) react: specifier: 18.2.0 version: 18.2.0 @@ -437,11 +455,11 @@ importers: specifier: ^3.4.1 version: 3.4.7(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) viem: - specifier: ^2.7.15 - version: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + specifier: 2.16.3 + version: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) wagmi: specifier: ^2.9.8 - version: 2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) + version: 2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) zod: specifier: 3.22.4 version: 3.22.4 @@ -517,7 +535,7 @@ importers: version: 9.1.0(eslint@8.57.0) eslint-import-resolver-typescript: specifier: ^3.6.1 - version: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) + version: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0) eslint-plugin-import: specifier: ^2.30.0 version: 2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) @@ -4521,6 +4539,14 @@ packages: permissionless: ^0.1.18 viem: ^2.16.3 + '@zerodev/passkey-validator@5.4.1': + resolution: {integrity: sha512-50mUDueqQGj2hCv//f+cHJ5paJy3aB5N+XI1ndcc7jNDcSKHvmINaQ12QyeH+NlchMnnzB/Iqix9YpeeGtB5KQ==} + peerDependencies: + '@zerodev/sdk': ^5.2.1 + '@zerodev/webauthn-key': ^5.3.0 + permissionless: '>=0.1.18 <=0.1.29' + viem: ^2.16.3 + '@zerodev/permissions@5.4.3': resolution: {integrity: sha512-rC5npYPRQO8lwhMXO6h2MXO3DGgRSDqAEVh9E2pRnlYPhaMDHRVd+nPqLIsx1OubRT0jSXrPFTQJd2MqeKcJ6w==} peerDependencies: @@ -4601,6 +4627,17 @@ packages: zod: optional: true + abitype@1.0.4: + resolution: {integrity: sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + abitype@1.0.5: resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} peerDependencies: @@ -9458,15 +9495,9 @@ packages: maci-core@2.2.0: resolution: {integrity: sha512-jHS40/uGJZMYvslfDls3LUPXK8gAijVrc8L8o51SJQX44iocgR3aWpWycD8df9rBCGBxScZPbtn04CmtFT0lhQ==} - maci-crypto@2.0.0: - resolution: {integrity: sha512-bkgOoDA1ABG49MXDzzsQPsFVEijAkLk8ocJKGyeNQS7YpNhC3YEVVz/SE4g0td+N4xJhD3PbXsyHeaTM3ApIjw==} - maci-crypto@2.2.0: resolution: {integrity: sha512-kSbWfuAdDWOdtQsEyofvgDIdAE//+iRjFdYjluDpvXnk7//x4t+/U4VEQJlE0kJ3TbCVjmsAaGNcbkmwmU977Q==} - maci-domainobjs@2.0.0: - resolution: {integrity: sha512-FmQdIC1omsWR/98wt8WvEJj0SDfnVTl9/2FMDp3N4WwUy1lzmmlVjUGKSFKj2+dj2Rx26DmBWsmKhbTIQeoPOQ==} - maci-domainobjs@2.2.0: resolution: {integrity: sha512-pPHqtdIHaPPvMGmWnmx7zXcXQM5+Q8ZGObeSEXgmH60ZKJTQgdoh5z+hs0TfLWEfoWmwWcetLl94EEfZQj0+vg==} @@ -13014,6 +13045,14 @@ packages: typescript: optional: true + viem@2.16.3: + resolution: {integrity: sha512-6ExbIpi77C1HzGSjx6W+fn39Cz1ULlVV74XHxi1kYpOAqY7/iAoynK5X2aQp2LvxstTqS1GIKEdpCAZ8dKi2Ag==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + viem@2.19.1: resolution: {integrity: sha512-a0ca/ACEz3FRZB3OmiSfRUogWZGQh700wu7Pg3GmAWiGD+0PS9bVaWG67JQ+9azFZLq0BU/m0t2CeWd3xi8IzQ==} peerDependencies: @@ -15340,12 +15379,12 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 - '@hatsprotocol/sdk-v1-core@0.10.0(encoding@0.1.13)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + '@hatsprotocol/sdk-v1-core@0.10.0(encoding@0.1.13)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: '@hatsprotocol/sdk-v1-subgraph': 1.0.0(encoding@0.1.13) graphql: 16.9.0 graphql-request: 6.1.0(encoding@0.1.13)(graphql@16.9.0) - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) transitivePeerDependencies: - encoding @@ -16558,6 +16597,27 @@ snapshots: typechain: 8.3.2(typescript@5.5.4) typescript: 5.5.4 + '@nomicfoundation/hardhat-toolbox@5.0.0(72yospjtc42fkew5yhzh5yik5m)': + dependencies: + '@nomicfoundation/hardhat-chai-matchers': 2.0.7(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.8(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition-ethers': 0.15.5(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-ignition@0.15.5(@nomicfoundation/hardhat-verify@2.0.9(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/ignition-core@0.15.5(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-network-helpers': 1.0.11(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-verify': 2.0.9(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + '@typechain/ethers-v6': 0.5.1(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4)) + '@types/chai': 4.3.17 + '@types/mocha': 10.0.7 + '@types/node': 20.14.14 + chai: 4.5.0 + ethers: 6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + hardhat: 2.22.8(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) + hardhat-gas-reporter: 1.0.10(bufferutil@4.0.8)(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + solidity-coverage: 0.8.12(hardhat@2.22.7(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) + typechain: 8.3.2(typescript@5.5.4) + typescript: 5.5.4 + '@nomicfoundation/hardhat-toolbox@5.0.0(hke34ef7km4fdyz52h5gry5opq)': dependencies: '@nomicfoundation/hardhat-chai-matchers': 2.0.7(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.8(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.8(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) @@ -17525,7 +17585,7 @@ snapshots: '@radix-ui/rect@1.1.0': {} - '@rainbow-me/rainbowkit@2.1.4(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4))': + '@rainbow-me/rainbowkit@2.1.4(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4))': dependencies: '@tanstack/react-query': 5.51.21(react@18.2.0) '@vanilla-extract/css': 1.14.0 @@ -17537,8 +17597,8 @@ snapshots: react-dom: 18.2.0(react@18.2.0) react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.2.0) ua-parser-js: 1.0.38 - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) - wagmi: 2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + wagmi: 2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) transitivePeerDependencies: - '@types/react' @@ -17940,7 +18000,7 @@ snapshots: '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)': dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.22.1 - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) transitivePeerDependencies: - bufferutil - typescript @@ -19103,17 +19163,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@wagmi/connectors@5.1.4(@types/react@18.3.3)(@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4)': + '@wagmi/connectors@5.1.4(@types/react@18.3.3)(@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4)': dependencies: '@coinbase/wallet-sdk': 4.0.4 '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) - '@wagmi/core': 2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@wagmi/core': 2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) '@walletconnect/ethereum-provider': 2.14.0(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10) '@walletconnect/modal': 2.6.2(@types/react@18.3.3)(react@18.2.0) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -19142,11 +19202,11 @@ snapshots: - utf-8-validate - zod - '@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + '@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.5.4) - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) zustand: 4.4.1(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0) optionalDependencies: '@tanstack/query-core': 5.51.21 @@ -19581,12 +19641,36 @@ snapshots: js-yaml: 3.14.1 tslib: 2.6.3 + '@zerodev/ecdsa-validator@5.3.1(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + permissionless: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/ecdsa-validator@5.3.1(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) permissionless: 0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/passkey-validator@5.4.1(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(@zerodev/webauthn-key@5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + '@noble/curves': 1.4.2 + '@simplewebauthn/browser': 8.3.7 + '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/webauthn-key': 5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + permissionless: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + + '@zerodev/permissions@5.4.3(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(@zerodev/webauthn-key@5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + '@simplewebauthn/browser': 9.0.1 + '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@zerodev/webauthn-key': 5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + merkletreejs: 0.3.11 + permissionless: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/permissions@5.4.3(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(@zerodev/webauthn-key@5.3.1(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: '@simplewebauthn/browser': 9.0.1 @@ -19596,12 +19680,25 @@ snapshots: permissionless: 0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + permissionless: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + semver: 7.6.3 + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: permissionless: 0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) semver: 7.6.3 viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/session-key@5.4.2(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + merkletreejs: 0.3.11 + permissionless: 0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/session-key@5.4.2(@zerodev/sdk@5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: '@zerodev/sdk': 5.3.9(permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) @@ -19609,6 +19706,12 @@ snapshots: permissionless: 0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/webauthn-key@5.3.1(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': + dependencies: + '@noble/curves': 1.4.2 + '@simplewebauthn/browser': 8.3.7 + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + '@zerodev/webauthn-key@5.3.1(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))': dependencies: '@noble/curves': 1.4.2 @@ -19671,6 +19774,11 @@ snapshots: typescript: 5.5.4 zod: 3.22.4 + abitype@1.0.4(typescript@5.5.4)(zod@3.22.4): + optionalDependencies: + typescript: 5.5.4 + zod: 3.22.4 + abitype@1.0.5(typescript@5.5.4)(zod@3.22.4): optionalDependencies: typescript: 5.5.4 @@ -22289,7 +22397,7 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) eslint-plugin-import: 2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.35.0(eslint@8.57.0) @@ -22312,12 +22420,29 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0): dependencies: debug: 4.3.6(supports-color@8.1.1) enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.6 + is-core-module: 2.15.0 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0): + dependencies: + debug: 4.3.6(supports-color@8.1.1) + enhanced-resolve: 5.17.1 + eslint: 8.57.0 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.6 @@ -22353,7 +22478,7 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -22368,14 +22493,24 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): + dependencies: + debug: 3.2.7(supports-color@8.1.1) + optionalDependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) + eslint: 8.57.0 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -26274,7 +26409,7 @@ snapshots: maci-contracts@2.3.0(tnqgnvgpfdbm2nfzhwjuiounlm): dependencies: '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.8(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-toolbox': 5.0.0(4lzaewf5vhmhgkr3zdkxldxwse) + '@nomicfoundation/hardhat-toolbox': 5.0.0(72yospjtc42fkew5yhzh5yik5m) '@openzeppelin/contracts': 5.0.2 circomlibjs: 0.1.7(bufferutil@4.0.8)(utf-8-validate@5.0.10) ethers: 6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -26316,16 +26451,6 @@ snapshots: - bufferutil - utf-8-validate - maci-crypto@2.0.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@zk-kit/baby-jubjub': 1.0.1 - '@zk-kit/eddsa-poseidon': 1.0.2 - '@zk-kit/poseidon-cipher': 0.3.1 - ethers: 6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - maci-crypto@2.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: '@zk-kit/baby-jubjub': 1.0.1 @@ -26336,13 +26461,6 @@ snapshots: - bufferutil - utf-8-validate - maci-domainobjs@2.0.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - maci-crypto: 2.0.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - maci-domainobjs@2.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: maci-crypto: 2.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -27990,6 +28108,10 @@ snapshots: performance-now@2.1.0: {} + permissionless@0.1.29(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)): + dependencies: + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + permissionless@0.1.29(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)): dependencies: viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) @@ -30667,6 +30789,23 @@ snapshots: - utf-8-validate - zod + viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4): + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/bip32': 1.3.2 + '@scure/bip39': 1.2.1 + abitype: 1.0.4(typescript@5.5.4)(zod@3.22.4) + isows: 1.0.4(ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4): dependencies: '@adraffy/ens-normalize': 1.10.0 @@ -30721,14 +30860,14 @@ snapshots: wabt@1.0.36: {} - wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4): + wagmi@2.12.4(@tanstack/query-core@5.51.21)(@tanstack/react-query@5.51.21(react@18.2.0))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.0.2)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4): dependencies: '@tanstack/react-query': 5.51.21(react@18.2.0) - '@wagmi/connectors': 5.1.4(@types/react@18.3.3)(@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) - '@wagmi/core': 2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) + '@wagmi/connectors': 5.1.4(@types/react@18.3.3)(@wagmi/core@2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.3(@babel/core@7.25.2))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@4.20.0)(typescript@5.5.4)(utf-8-validate@5.0.10)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4))(zod@3.22.4) + '@wagmi/core': 2.13.3(@tanstack/query-core@5.51.21)(@types/react@18.3.3)(immer@10.0.2)(react@18.2.0)(typescript@5.5.4)(viem@2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4)) react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.19.1(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.16.3(bufferutil@4.0.8)(typescript@5.5.4)(utf-8-validate@5.0.10)(zod@3.22.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: