From ad1570512b4cc6ff60e7cda2b6c6e177f745df1f Mon Sep 17 00:00:00 2001 From: BoHsuu Date: Fri, 3 Apr 2026 15:15:06 +0700 Subject: [PATCH 1/2] feat: migrate proving system from UltraPlonk to UltraHonk --- docs/adr/001-dynamic-import-aztec-bb-js.md | 31 +++++ docs/adr/002-ultrahonk-migration.md | 57 ++++++++ docs/zero-knowledge-implementation.md | 4 +- docs/zkverify-horizen-integration.md | 4 +- .../backend/assets/vkey-auth-ultrahonk.json | 1 + ...ey-auth.json => vkey-auth-ultraplonk.json} | 0 .../assets/vkey-transaction-ultrahonk.json | 1 + ....json => vkey-transaction-ultraplonk.json} | 0 .../backend/src/account/account.service.ts | 4 + packages/backend/src/auth/auth.service.ts | 2 + .../src/transaction/transaction.service.ts | 2 + packages/backend/src/user/user.service.ts | 1 + .../backend/src/zkverify/zkverify.service.ts | 122 +++++++++++++----- packages/backend/test/utils/auth.util.ts | 1 + packages/backend/test/utils/proof.util.ts | 37 ++++-- .../backend/test/utils/transaction.util.ts | 2 + .../hardhat/contracts/MetaMultiSigWallet.sol | 2 +- .../horizenTestnet/MetaMultiSigWallet.json | 46 +++---- .../10833bafee6b78acc8e4896ca53dfe58.json | 39 ++++++ .../nextjs/contracts/deployedContracts.ts | 4 +- .../app/transaction/useBatchTransaction.ts | 2 +- .../app/transaction/useSignerTransaction.ts | 2 +- .../app/transaction/useTransactionVote.ts | 2 +- .../app/transaction/useTransferTransaction.ts | 2 +- packages/nextjs/hooks/app/useAuth.ts | 2 +- packages/nextjs/hooks/app/useAuthProof.ts | 11 +- packages/nextjs/hooks/app/useGenerateProof.ts | 31 +++-- .../src/contracts/MetaMultiSigWallet.ts | 2 +- .../shared/src/contracts/contracts-config.ts | 8 +- packages/shared/src/types/account.ts | 1 + 30 files changed, 330 insertions(+), 93 deletions(-) create mode 100644 docs/adr/001-dynamic-import-aztec-bb-js.md create mode 100644 docs/adr/002-ultrahonk-migration.md create mode 100644 packages/backend/assets/vkey-auth-ultrahonk.json rename packages/backend/assets/{vkey-auth.json => vkey-auth-ultraplonk.json} (100%) create mode 100644 packages/backend/assets/vkey-transaction-ultrahonk.json rename packages/backend/assets/{vkey-transaction.json => vkey-transaction-ultraplonk.json} (100%) create mode 100644 packages/hardhat/deployments/horizenTestnet/solcInputs/10833bafee6b78acc8e4896ca53dfe58.json diff --git a/docs/adr/001-dynamic-import-aztec-bb-js.md b/docs/adr/001-dynamic-import-aztec-bb-js.md new file mode 100644 index 00000000..c098fa7f --- /dev/null +++ b/docs/adr/001-dynamic-import-aztec-bb-js.md @@ -0,0 +1,31 @@ +# ADR-001: Dynamic import for @aztec/bb.js + +## Status + +Accepted + +## Context + +`@aztec/bb.js` is a heavy WASM-based cryptographic library used for ZK proof generation (UltraHonk/UltraPlonk backends). It is only needed when users perform specific actions: signing transactions, approving votes, or authenticating with ZK proofs. + +If imported statically (`import { UltraHonkBackend } from '@aztec/bb.js'`), Next.js bundles the entire library into the initial JS chunk. This significantly increases the first load JS size for every page, even pages that never generate proofs. + +## Decision + +Use dynamic `import()` for `@aztec/bb.js` (and `@noir-lang/noir_js`) at the point of use inside proof generation hooks: + +```typescript +// Instead of top-level static import +const { UltraHonkBackend } = await import("@aztec/bb.js"); +const { Noir } = await import("@noir-lang/noir_js"); +``` + +This applies to: +- `packages/nextjs/hooks/app/useGenerateProof.ts` +- `packages/nextjs/hooks/app/useAuthProof.ts` + +## Consequences + +- First load JS stays small — cryptographic libraries are only fetched when a user initiates a proof generation action +- Slight delay when generating the first proof in a session (library download + WASM initialization), but this is acceptable since proof generation itself already takes seconds +- Must use `await import()` pattern consistently — never add static imports for these packages in frontend code diff --git a/docs/adr/002-ultrahonk-migration.md b/docs/adr/002-ultrahonk-migration.md new file mode 100644 index 00000000..57ddda0e --- /dev/null +++ b/docs/adr/002-ultrahonk-migration.md @@ -0,0 +1,57 @@ +# ADR-002: UltraPlonk to UltraHonk Migration + +## Status + +Accepted + +## Context + +UltraPlonk is deprecated from bbup v0.87.0+. zkVerify supports UltraHonk as replacement. Migration needed across the full stack: frontend proof generation, backend proof submission (Kurier API), and smart contract verification. + +## Decision + +New accounts (contractVersion >= 2) use UltraHonk. Old accounts (contractVersion 1) continue using UltraPlonk. The `contractVersion` field on the Account model drives all branching. + +## Key Findings (not obvious from docs) + +### 1. `{ keccak: true }` is mandatory + +zkVerify only supports Keccak256 hash for UltraHonk. bb.js defaults to non-keccak. Must pass `{ keccak: true }` to both `generateProof` and `getVerificationKey`: + +```typescript +const backend = new UltraHonkBackend(bytecode); +const { proof, publicInputs } = await backend.generateProof(witness, { keccak: true }); +const vk = await backend.getVerificationKey({ keccak: true }); +``` + +Without keccak, the VK size is 1825 bytes instead of expected 1760 bytes, and proofs won't verify. + +### 2. Variant must be `'Plain'`, not `'ZK'` + +bb.js `acirProveUltraKeccakHonk` generates **Plain** (non-ZK) proofs. There is no `--zk` option in the bb.js API. Using `variant: 'ZK'` causes proof verification to fail silently (`optimisticVerify: "failed"`). + +### 3. Kurier API format differs completely from UltraPlonk + +| Aspect | UltraPlonk | UltraHonk | +|--------|-----------|----------| +| VK encoding | base64 | hex `0x`-prefixed | +| Proof encoding | base64 (public inputs concatenated) | hex `0x`-prefixed | +| Public inputs | Concatenated into proof bytes | Separate `publicSignals` array | +| proofOptions (register-vk) | `{ numberOfPublicInputs }` | `{ variant: 'Plain' }` | +| proofOptions (submit-proof) | `{ numberOfPublicInputs }` | `{ variant: 'Plain' }` | + +### 4. VK file naming includes proof type + +VK files use the pattern `vkey-{circuitType}-{proofType}.json` to support both systems simultaneously: +- `vkey-transaction-ultraplonk.json` (old accounts) +- `vkey-transaction-ultrahonk.json` (new accounts) + +### 5. Smart contract vkHash must match + +The `vkHash` in `contracts-config.ts` is used when deploying new multisig contracts. It must match the vkHash from the UltraHonk VK registration on zkVerify. Old deployed contracts are unaffected (vkHash is immutable). + +## Consequences + +- Both proving systems coexist — no breaking changes for existing accounts +- `contractVersion` must be included in ALL API responses that return account data (including `user.service.ts getAccounts`) +- Future bb.js versions may add ZK support — at that point, switch variant from `'Plain'` to `'ZK'` for better privacy diff --git a/docs/zero-knowledge-implementation.md b/docs/zero-knowledge-implementation.md index c2de7295..c3b4ab50 100644 --- a/docs/zero-knowledge-implementation.md +++ b/docs/zero-knowledge-implementation.md @@ -20,7 +20,7 @@ In PolyPay: ## The Four Proofs -When you sign a transaction in PolyPay, the ZK circuit proves four things simultaneously. The circuit is written in [Noir](https://noir-lang.org), a domain-specific language for zero-knowledge proofs, and compiled to [UltraPlonk](https://rknhr-uec.github.io/aztec-protocol-spec/protocol-specs/cryptography/proving-system/overview) for efficient verification. +When you sign a transaction in PolyPay, the ZK circuit proves four things simultaneously. The circuit is written in [Noir](https://noir-lang.org), a domain-specific language for zero-knowledge proofs. New accounts use [UltraHonk](https://docs.zkverify.io/architecture/verification_pallets/ultrahonk) as the proving backend, while legacy accounts (contractVersion 1) continue using UltraPlonk. ### Proof 1: "I know the transaction" @@ -108,5 +108,5 @@ This two-step verification ensures only authorized signers can sign transactions ## Learn More - [Noir Language Documentation](https://noir-lang.org/docs) -- [UltraPlonk Proving System](https://rknhr-uec.github.io/aztec-protocol-spec/protocol-specs/cryptography/proving-system/overview) +- [UltraHonk Proving System](https://docs.zkverify.io/architecture/verification_pallets/ultrahonk) - [zkVerify Documentation](https://docs.zkverify.io) diff --git a/docs/zkverify-horizen-integration.md b/docs/zkverify-horizen-integration.md index fa4d9caa..34f8a9a3 100644 --- a/docs/zkverify-horizen-integration.md +++ b/docs/zkverify-horizen-integration.md @@ -4,7 +4,7 @@ PolyPay uses multiple blockchain layers for privacy-preserving multisig operations: -- **[zkVerify](https://docs.zkverify.io/)**: Verifies zero-knowledge proofs (ultraplonk) off-chain, providing proof verification and aggregation as a service +- **[zkVerify](https://docs.zkverify.io/)**: Verifies zero-knowledge proofs off-chain (UltraHonk for new accounts, UltraPlonk for legacy accounts), providing proof verification and aggregation as a service - **[Horizen](https://www.horizen.io/)**: EVM-compatible L3 blockchain where multisig accounts (`MetaMultiSigWallet` contracts) are deployed and transactions are executed - **[Base](https://base.org/)**: EVM-compatible L2 blockchain, also supported as a destination chain for account deployment and transaction execution @@ -33,7 +33,7 @@ User proves ownership of their commitment without revealing the secret. ![Authentication Flow](.gitbook/assets/zkverify-horizen/authentication-flow.png) -- **zkVerify**: Verify ultraplonk proof, return `jobId` and `zkVerifyTxHash` +- **zkVerify**: Verify proof (UltraHonk or UltraPlonk based on account version), return `jobId` and `zkVerifyTxHash` - **Destination chain**: No interaction ### 2. Account Creation (CREATE_ACCOUNT) diff --git a/packages/backend/assets/vkey-auth-ultrahonk.json b/packages/backend/assets/vkey-auth-ultrahonk.json new file mode 100644 index 00000000..acf8fe05 --- /dev/null +++ b/packages/backend/assets/vkey-auth-ultrahonk.json @@ -0,0 +1 @@ +{"vkHash":"0x7c3f7708bd192d01a1740da057d05e1ed48bd8733e54bda264a151449a66996d"} \ No newline at end of file diff --git a/packages/backend/assets/vkey-auth.json b/packages/backend/assets/vkey-auth-ultraplonk.json similarity index 100% rename from packages/backend/assets/vkey-auth.json rename to packages/backend/assets/vkey-auth-ultraplonk.json diff --git a/packages/backend/assets/vkey-transaction-ultrahonk.json b/packages/backend/assets/vkey-transaction-ultrahonk.json new file mode 100644 index 00000000..e8cfc6f8 --- /dev/null +++ b/packages/backend/assets/vkey-transaction-ultrahonk.json @@ -0,0 +1 @@ +{"vkHash":"0xb3c5381523a496996868370791ec7ae490be7e2c996296fb67708daed8a6ea38"} \ No newline at end of file diff --git a/packages/backend/assets/vkey-transaction.json b/packages/backend/assets/vkey-transaction-ultraplonk.json similarity index 100% rename from packages/backend/assets/vkey-transaction.json rename to packages/backend/assets/vkey-transaction-ultraplonk.json diff --git a/packages/backend/src/account/account.service.ts b/packages/backend/src/account/account.service.ts index 1b173850..36d7a04f 100644 --- a/packages/backend/src/account/account.service.ts +++ b/packages/backend/src/account/account.service.ts @@ -86,6 +86,7 @@ export class AccountService { name: dto.name, threshold: dto.threshold, chainId: dto.chainId, + contractVersion: 2, }, }); @@ -235,6 +236,7 @@ export class AccountService { name: dto.name, threshold: dto.threshold, chainId: deployment.chainId, + contractVersion: 2, }, }); @@ -349,6 +351,7 @@ export class AccountService { name: string | null; threshold: number; chainId: number; + contractVersion: number; createdAt: Date; signers: Array<{ isCreator: boolean; @@ -362,6 +365,7 @@ export class AccountService { name: account.name, threshold: account.threshold, chainId: account.chainId, + contractVersion: account.contractVersion, createdAt: account.createdAt, signers: account.signers.map((as) => ({ commitment: as.user.commitment, diff --git a/packages/backend/src/auth/auth.service.ts b/packages/backend/src/auth/auth.service.ts index 3e49fed6..1ce52054 100644 --- a/packages/backend/src/auth/auth.service.ts +++ b/packages/backend/src/auth/auth.service.ts @@ -37,6 +37,8 @@ export class AuthService { vk: dto.vk, }, 'auth', + undefined, + 2, ); } catch (error) { this.logger.error(`Proof verification failed: ${error.message}`); diff --git a/packages/backend/src/transaction/transaction.service.ts b/packages/backend/src/transaction/transaction.service.ts index e4695ba2..d3e4de84 100644 --- a/packages/backend/src/transaction/transaction.service.ts +++ b/packages/backend/src/transaction/transaction.service.ts @@ -125,6 +125,7 @@ export class TransactionService { }, 'transaction', account.chainId, + account.contractVersion, ); // 5. Create transaction + first vote + delete reservation @@ -268,6 +269,7 @@ export class TransactionService { }, 'transaction', transaction.account.chainId, + transaction.account.contractVersion, ); const voterName = await this.getSignerDisplayName( diff --git a/packages/backend/src/user/user.service.ts b/packages/backend/src/user/user.service.ts index 67446ed2..f7208f8d 100644 --- a/packages/backend/src/user/user.service.ts +++ b/packages/backend/src/user/user.service.ts @@ -81,6 +81,7 @@ export class UserService { name: account.name, threshold: account.threshold, chainId: account.chainId, + contractVersion: account.contractVersion, createdAt: account.createdAt, signers: account.signers.map((signer) => ({ commitment: signer.user.commitment, diff --git a/packages/backend/src/zkverify/zkverify.service.ts b/packages/backend/src/zkverify/zkverify.service.ts index d4fe80ff..cf32eb38 100644 --- a/packages/backend/src/zkverify/zkverify.service.ts +++ b/packages/backend/src/zkverify/zkverify.service.ts @@ -24,6 +24,14 @@ import { export type CircuitType = 'transaction' | 'auth'; +function getProofType(contractVersion: number): string { + return contractVersion >= 2 ? 'ultrahonk' : 'ultraplonk'; +} + +function bytesToHex(bytes: Uint8Array): string { + return '0x' + Buffer.from(bytes).toString('hex'); +} + @Injectable() export class ZkVerifyService { private readonly logger = new Logger(ZkVerifyService.name); @@ -52,8 +60,12 @@ export class ZkVerifyService { /** * Get vkey file path by circuit type */ - private getVkeyPath(circuitType: CircuitType): string { - return path.join(this.assetsDir, `vkey-${circuitType}.json`); + private getVkeyPath( + circuitType: CircuitType, + contractVersion: number, + ): string { + const proofType = getProofType(contractVersion); + return path.join(this.assetsDir, `vkey-${circuitType}-${proofType}.json`); } private async retryRequest( @@ -81,6 +93,11 @@ export class ZkVerifyService { this.logger.error( `${operationName} failed after ${attempt} attempts: ${error.message}`, ); + if (error.response?.data) { + this.logger.error( + `Response body: ${JSON.stringify(error.response.data)}`, + ); + } throw error; } @@ -108,32 +125,54 @@ export class ZkVerifyService { }, circuitType: CircuitType = 'transaction', chainId?: number, + contractVersion: number = 1, ): Promise<{ jobId: string; status: string; txHash?: string }> { const proofUint8 = new Uint8Array(dto.proof); const numberOfPublicInputs = dto.publicInputs?.length || 1; - const vk = await this.loadOrRegisterVk( + const vkHash = await this.loadOrRegisterVk( circuitType, + contractVersion, dto.vk, numberOfPublicInputs, ); const effectiveChainId = chainId ?? this.defaultChainId; - const params = { - proofType: 'ultraplonk', - vkRegistered: true, - chainId: effectiveChainId, - proofOptions: { - numberOfPublicInputs, - }, - proofData: { - proof: Buffer.from( - this.concatenatePublicInputsAndProof(dto.publicInputs, proofUint8), - ).toString('base64'), - vk, - }, - }; + const proofType = getProofType(contractVersion); + + let params: Record; + + if (contractVersion >= 2) { + // UltraHonk: hex proof + separate publicSignals + params = { + proofType, + vkRegistered: true, + chainId: effectiveChainId, + proofOptions: { variant: 'Plain' }, + proofData: { + proof: bytesToHex(proofUint8), + publicSignals: dto.publicInputs, + vk: vkHash, + }, + }; + } else { + // UltraPlonk: base64-encoded proof with concatenated public inputs + params = { + proofType, + vkRegistered: true, + chainId: effectiveChainId, + proofOptions: { numberOfPublicInputs }, + proofData: { + proof: Buffer.from( + this.concatenatePublicInputsAndProof(dto.publicInputs, proofUint8), + ).toString('base64'), + vk: vkHash, + }, + }; + } - this.logger.log(`Submitting ${circuitType} proof to zkVerify...`); + this.logger.log( + `Submitting ${circuitType} proof (${proofType}) to zkVerify...`, + ); const submitResponse = await this.retryRequest( () => axios.post( @@ -146,6 +185,9 @@ export class ZkVerifyService { ); if (submitResponse.data.optimisticVerify !== 'success') { + this.logger.error( + `Proof verification failed. Response: ${JSON.stringify(submitResponse.data)}`, + ); throw new BadRequestException('Proof verification failed'); } @@ -204,18 +246,32 @@ export class ZkVerifyService { */ private async registerVk( circuitType: CircuitType, + contractVersion: number, vk: string, numberOfPublicInputs: number, ): Promise { - const vkeyPath = this.getVkeyPath(circuitType); - - const params = { - proofType: 'ultraplonk', - vk, - proofOptions: { - numberOfPublicInputs, - }, - }; + const vkeyPath = this.getVkeyPath(circuitType, contractVersion); + const proofType = getProofType(contractVersion); + + let params: Record; + + if (contractVersion >= 2) { + // UltraHonk: hex VK + const hexVk = + typeof vk === 'string' && !vk.startsWith('0x') ? `0x${vk}` : vk; + params = { + proofType, + vk: hexVk, + proofOptions: { variant: 'Plain' }, + }; + } else { + // UltraPlonk: base64 VK, numberOfPublicInputs in proofOptions + params = { + proofType, + vk, + proofOptions: { numberOfPublicInputs }, + }; + } try { this.logger.log(`Registering VK for ${circuitType} circuit...`); @@ -252,18 +308,24 @@ export class ZkVerifyService { */ private async loadOrRegisterVk( circuitType: CircuitType, + contractVersion: number, vk?: string, numberOfPublicInputs?: number, ): Promise { - const vkeyPath = this.getVkeyPath(circuitType); + const vkeyPath = this.getVkeyPath(circuitType, contractVersion); if (!fs.existsSync(vkeyPath)) { if (!vk) { throw new BadRequestException( - `VK required for first registration of ${circuitType} circuit`, + `VK required for first registration of ${circuitType} circuit (${getProofType(contractVersion)})`, ); } - await this.registerVk(circuitType, vk, numberOfPublicInputs); + await this.registerVk( + circuitType, + contractVersion, + vk, + numberOfPublicInputs, + ); await new Promise((resolve) => setTimeout(resolve, ZK_POLLING_DELAY)); } diff --git a/packages/backend/test/utils/auth.util.ts b/packages/backend/test/utils/auth.util.ts index bf916662..3dd08a4b 100644 --- a/packages/backend/test/utils/auth.util.ts +++ b/packages/backend/test/utils/auth.util.ts @@ -27,6 +27,7 @@ export async function loginUser( commitment, proof: authProof.proof, publicInputs: authProof.publicInputs, + vk: authProof.vk, }) .expect(201); diff --git a/packages/backend/test/utils/proof.util.ts b/packages/backend/test/utils/proof.util.ts index 8c9afde9..77f29e23 100644 --- a/packages/backend/test/utils/proof.util.ts +++ b/packages/backend/test/utils/proof.util.ts @@ -17,6 +17,7 @@ export interface ProofResult { publicInputs: string[]; nullifier: string; commitment: string; + vk?: string; } /** @@ -25,6 +26,7 @@ export interface ProofResult { export interface AuthProofResult { proof: number[]; publicInputs: string[]; + vk: string; } /** @@ -58,6 +60,7 @@ export async function generateTestProof( signer: TestSigner, secret: bigint, txHash: Hex, + contractVersion: number = 2, ): Promise { // 1. Sign txHash (local signing, no RPC) const signature = await signRawMessage(signer, txHash); @@ -94,17 +97,31 @@ export async function generateTestProof( // Dynamic import Noir libraries const { Noir } = await import('@noir-lang/noir_js'); - const { UltraPlonkBackend } = await import('@aztec/bb.js'); - // Initialize Noir and backend - const backend = new UltraPlonkBackend(bytecode); + // Initialize Noir const noir = new Noir({ bytecode, abi } as any); // Execute circuit const { witness } = await noir.execute(circuitInputs); - // Generate proof - const { proof, publicInputs } = await backend.generateProof(witness); + // Generate proof — branch by contractVersion + let proof: Uint8Array; + let publicInputs: string[]; + let vk: string | undefined; + + if (contractVersion >= 2) { + const { UltraHonkBackend } = await import('@aztec/bb.js'); + const backend = new UltraHonkBackend(bytecode); + ({ proof, publicInputs } = await backend.generateProof(witness, { keccak: true })); + const rawVk = await backend.getVerificationKey({ keccak: true }); + vk = '0x' + Buffer.from(rawVk).toString('hex'); + } else { + const { UltraPlonkBackend } = await import('@aztec/bb.js'); + const backend = new UltraPlonkBackend(bytecode); + ({ proof, publicInputs } = await backend.generateProof(witness)); + const rawVk = await backend.getVerificationKey(); + vk = Buffer.from(rawVk).toString('base64'); + } // 7. Format output const proofArray = Array.from(proof); @@ -114,6 +131,7 @@ export async function generateTestProof( publicInputs: publicInputs, nullifier: nullifier.toString(), commitment: commitment.toString(), + vk, }; } @@ -136,17 +154,20 @@ export async function generateTestAuthProof( const { bytecode, abi } = loadCircuit('auth-circuit'); const { Noir } = await import('@noir-lang/noir_js'); - const { UltraPlonkBackend } = await import('@aztec/bb.js'); + const { UltraHonkBackend } = await import('@aztec/bb.js'); - const backend = new UltraPlonkBackend(bytecode); + const backend = new UltraHonkBackend(bytecode); const noir = new Noir({ bytecode, abi } as any); const { witness } = await noir.execute(circuitInputs); - const { proof, publicInputs } = await backend.generateProof(witness); + const { proof, publicInputs } = await backend.generateProof(witness, { keccak: true }); + const rawVk = await backend.getVerificationKey({ keccak: true }); + const vk = '0x' + Buffer.from(rawVk).toString('hex'); return { proof: Array.from(proof), publicInputs: publicInputs, + vk, }; } diff --git a/packages/backend/test/utils/transaction.util.ts b/packages/backend/test/utils/transaction.util.ts index 22458d44..2b355662 100644 --- a/packages/backend/test/utils/transaction.util.ts +++ b/packages/backend/test/utils/transaction.util.ts @@ -29,6 +29,7 @@ export interface ApproveTransactionPayload { proof: number[]; publicInputs: string[]; nullifier: string; + vk?: string; } export interface ParsedTokenAmount { @@ -164,6 +165,7 @@ export async function generateVotePayload( proof: proof.proof, publicInputs: proof.publicInputs, nullifier: proof.nullifier, + vk: proof.vk, }; } diff --git a/packages/hardhat/contracts/MetaMultiSigWallet.sol b/packages/hardhat/contracts/MetaMultiSigWallet.sol index 2725b005..a5620963 100644 --- a/packages/hardhat/contracts/MetaMultiSigWallet.sol +++ b/packages/hardhat/contracts/MetaMultiSigWallet.sol @@ -16,7 +16,7 @@ interface IVerifyProofAggregation { contract MetaMultiSigWallet { // ============ Constants ============ - bytes32 public constant PROVING_SYSTEM_ID = keccak256(abi.encodePacked("ultraplonk")); + bytes32 public constant PROVING_SYSTEM_ID = keccak256(abi.encodePacked("ultrahonk")); bytes32 public constant VERSION_HASH = sha256(abi.encodePacked("")); uint256 public constant BN254_PRIME = 21888242871839275222246405745257275088548364400416034343698204186575808495617; diff --git a/packages/hardhat/deployments/horizenTestnet/MetaMultiSigWallet.json b/packages/hardhat/deployments/horizenTestnet/MetaMultiSigWallet.json index da237d97..664903f6 100644 --- a/packages/hardhat/deployments/horizenTestnet/MetaMultiSigWallet.json +++ b/packages/hardhat/deployments/horizenTestnet/MetaMultiSigWallet.json @@ -1,5 +1,5 @@ { - "address": "0x1EaCA128069b2bb1cd476ef66E2701F98cAB148E", + "address": "0xE146bA86fef4056566D7EE9dBB9fFaCf8A994AC2", "abi": [ { "inputs": [ @@ -516,46 +516,46 @@ "type": "receive" } ], - "transactionHash": "0xc1302204330b385b9de7bbf5e64fdbbb76f85456bf14790e916ab51cd28672bd", + "transactionHash": "0x26a9569812e49352da904f4ef500ce3b4e50089e7a1bad193cb7afaffccfce2c", "receipt": { "to": null, - "from": "0x7ccC1D51a0588a7fc1Ce4bA9200a60ea7d736006", - "contractAddress": "0x1EaCA128069b2bb1cd476ef66E2701F98cAB148E", + "from": "0xd95E85e86D3Be5C86846435b8F0C3a476C5a9e42", + "contractAddress": "0xE146bA86fef4056566D7EE9dBB9fFaCf8A994AC2", "transactionIndex": 1, - "gasUsed": "1970726", - "logsBloom": "0x00000000000000000000200000000000000000000000000010000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000400000000000000000000000000000000000000201000020000000000000000000000000000000080000000000000000000000000000000000000000000001000000000000000000000000000", - "blockHash": "0xc8dcc49001046996193df411cc8811f9e9f74dad9bba02221588f71777524f70", - "transactionHash": "0xc1302204330b385b9de7bbf5e64fdbbb76f85456bf14790e916ab51cd28672bd", + "gasUsed": "1970282", + "logsBloom": "0x00000000000000000000000000000000000100000000000010000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000080000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000400000000000000000000000000000000000000001000000000000000000000000000000000000080000000000000000000000000000001000000000000001000000000000000000000000000", + "blockHash": "0xa98600e7dcc677118d5404bca6cedd088e86d2484f5d89c296feed9586f0e0ca", + "transactionHash": "0x26a9569812e49352da904f4ef500ce3b4e50089e7a1bad193cb7afaffccfce2c", "logs": [ { "transactionIndex": 1, - "blockNumber": 6615581, - "transactionHash": "0xc1302204330b385b9de7bbf5e64fdbbb76f85456bf14790e916ab51cd28672bd", - "address": "0x1EaCA128069b2bb1cd476ef66E2701F98cAB148E", + "blockNumber": 13507810, + "transactionHash": "0x26a9569812e49352da904f4ef500ce3b4e50089e7a1bad193cb7afaffccfce2c", + "address": "0xE146bA86fef4056566D7EE9dBB9fFaCf8A994AC2", "topics": [ "0x33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d", "0x1131dc18975dba9108c1928c196d11a9a0ad0fcfb0669f9abf20bb96edeafff6" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", "logIndex": 0, - "blockHash": "0xc8dcc49001046996193df411cc8811f9e9f74dad9bba02221588f71777524f70" + "blockHash": "0xa98600e7dcc677118d5404bca6cedd088e86d2484f5d89c296feed9586f0e0ca" }, { "transactionIndex": 1, - "blockNumber": 6615581, - "transactionHash": "0xc1302204330b385b9de7bbf5e64fdbbb76f85456bf14790e916ab51cd28672bd", - "address": "0x1EaCA128069b2bb1cd476ef66E2701F98cAB148E", + "blockNumber": 13507810, + "transactionHash": "0x26a9569812e49352da904f4ef500ce3b4e50089e7a1bad193cb7afaffccfce2c", + "address": "0xE146bA86fef4056566D7EE9dBB9fFaCf8A994AC2", "topics": [ "0x33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d", "0x089be75650f2d8f6619f7aee1349a6327ed4b35b551c593c174f62d65637cc39" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", "logIndex": 1, - "blockHash": "0xc8dcc49001046996193df411cc8811f9e9f74dad9bba02221588f71777524f70" + "blockHash": "0xa98600e7dcc677118d5404bca6cedd088e86d2484f5d89c296feed9586f0e0ca" } ], - "blockNumber": 6615581, - "cumulativeGasUsed": "2014582", + "blockNumber": 13507810, + "cumulativeGasUsed": "2014138", "status": 1, "byzantium": true }, @@ -569,11 +569,11 @@ ], 2 ], - "numDeployments": 1, - "solcInputHash": "d03f78c52deb4ca4d79043526c9d68f9", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_zkvContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_vkHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"_initialCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_signaturesRequired\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"commitment\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isAdded\",\"type\":\"bool\"}],\"name\":\"Owner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"name\":\"TransactionExecuted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BN254_PRIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVING_SYSTEM_ID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION_HASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"newCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"addSigners\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"batchTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddresses\",\"type\":\"address[]\"}],\"name\":\"batchTransferMulti\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"commitments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"commitment\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nullifier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"aggregationId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"domainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"zkMerklePath\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"internalType\":\"struct MetaMultiSigWallet.ZkProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCommitments\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSignersCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getTransactionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"name\":\"poseidonHash2\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"commitmentsToRemove\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"removeSigners\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"signaturesRequired\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"updateSignaturesRequired\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedNonces\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedNullifiers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vkHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zkvContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"batchTransfer(address[],uint256[])\":{\"params\":{\"amounts\":\"Array of amounts to send\",\"recipients\":\"Array of recipient addresses\"}},\"batchTransferMulti(address[],uint256[],address[])\":{\"params\":{\"amounts\":\"Array of amounts to send\",\"recipients\":\"Array of recipient addresses\",\"tokenAddresses\":\"Array of token addresses (address(0) = native ETH)\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"batchTransfer(address[],uint256[])\":{\"notice\":\"Execute multiple transfers in one transaction\"},\"batchTransferMulti(address[],uint256[],address[])\":{\"notice\":\"Execute multiple transfers with mixed token types\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MetaMultiSigWallet.sol\":\"MetaMultiSigWallet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/MetaMultiSigWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport \\\"poseidon-solidity/PoseidonT3.sol\\\";\\n\\ninterface IVerifyProofAggregation {\\n function verifyProofAggregation(\\n uint256 _domainId,\\n uint256 _aggregationId,\\n bytes32 _leaf,\\n bytes32[] calldata _merklePath,\\n uint256 _leafCount,\\n uint256 _index\\n ) external view returns (bool);\\n}\\n\\ncontract MetaMultiSigWallet {\\n // ============ Constants ============\\n bytes32 public constant PROVING_SYSTEM_ID = keccak256(abi.encodePacked(\\\"ultraplonk\\\"));\\n bytes32 public constant VERSION_HASH = sha256(abi.encodePacked(\\\"\\\"));\\n uint256 public constant BN254_PRIME = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\\n\\n // ============ Events ============\\n event Deposit(address indexed sender, uint256 amount, uint256 balance);\\n event TransactionExecuted(uint256 indexed nonce, address to, uint256 value, bytes data, bytes result);\\n event Owner(uint256 indexed commitment, bool isAdded);\\n\\n // ============ Structs ============\\n struct ZkProof {\\n uint256 commitment;\\n uint256 nullifier;\\n uint256 aggregationId;\\n uint256 domainId;\\n bytes32[] zkMerklePath;\\n uint256 leafCount;\\n uint256 index;\\n }\\n\\n // ============ State ============\\n address public immutable zkvContract;\\n bytes32 public immutable vkHash;\\n uint256 public chainId;\\n uint256 public signaturesRequired;\\n\\n // Signer management\\n uint256[] public commitments;\\n\\n // Nonce tracking (prevent replay)\\n mapping(uint256 => bool) public usedNonces;\\n\\n // Nullifier tracking (prevent double-signing)\\n mapping(uint256 => bool) public usedNullifiers;\\n\\n // ============ Constructor ============\\n constructor(\\n address _zkvContract,\\n bytes32 _vkHash,\\n uint256 _chainId,\\n uint256[] memory _initialCommitments,\\n uint256 _signaturesRequired\\n ) {\\n require(_zkvContract != address(0), \\\"Invalid zkv address\\\");\\n require(_signaturesRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(_initialCommitments.length > 0, \\\"Need at least 1 signer\\\");\\n require(_signaturesRequired <= _initialCommitments.length, \\\"Sigs required too high\\\");\\n\\n zkvContract = _zkvContract;\\n vkHash = _vkHash;\\n chainId = _chainId;\\n signaturesRequired = _signaturesRequired;\\n\\n for (uint256 i = 0; i < _initialCommitments.length; i++) {\\n require(_initialCommitments[i] != 0, \\\"Invalid commitment\\\");\\n commitments.push(_initialCommitments[i]);\\n emit Owner(_initialCommitments[i], true);\\n }\\n }\\n\\n // ============ Modifiers ============\\n modifier onlySelf() {\\n require(msg.sender == address(this), \\\"Not Self\\\");\\n _;\\n }\\n\\n // ============ Main Execute Function ============\\n function execute(\\n uint256 _nonce,\\n address to,\\n uint256 value,\\n bytes calldata data,\\n ZkProof[] calldata proofs\\n ) external returns (bytes memory) {\\n require(!usedNonces[_nonce], \\\"Nonce already used\\\");\\n require(proofs.length >= signaturesRequired, \\\"Not enough proofs\\\");\\n\\n bytes32 txHash = keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\\n\\n for (uint256 i = 0; i < proofs.length; i++) {\\n require(!usedNullifiers[proofs[i].nullifier], \\\"Nullifier already used\\\");\\n require(_isCurrentSigner(proofs[i].commitment), \\\"Not a current signer\\\");\\n require(_verifyProof(txHash, proofs[i]), \\\"Invalid proof\\\");\\n usedNullifiers[proofs[i].nullifier] = true;\\n }\\n\\n usedNonces[_nonce] = true;\\n\\n (bool success, bytes memory result) = to.call{ value: value }(data);\\n require(success, \\\"Tx failed\\\");\\n\\n emit TransactionExecuted(_nonce, to, value, data, result);\\n return result;\\n }\\n\\n // ============ Signer Management ============\\n function addSigners(uint256[] calldata newCommitments, uint256 newSigRequired) public onlySelf {\\n require(newCommitments.length > 0, \\\"Empty array\\\");\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length + newCommitments.length, \\\"Sigs required too high\\\");\\n\\n for (uint256 i = 0; i < newCommitments.length; i++) {\\n require(newCommitments[i] != 0, \\\"Invalid commitment\\\");\\n \\n // Check duplicate with existing signers\\n for (uint256 j = 0; j < commitments.length; j++) {\\n require(commitments[j] != newCommitments[i], \\\"Commitment exists\\\");\\n }\\n \\n // Check duplicate within input array\\n for (uint256 k = 0; k < i; k++) {\\n require(newCommitments[k] != newCommitments[i], \\\"Duplicate in input\\\");\\n }\\n\\n commitments.push(newCommitments[i]);\\n emit Owner(newCommitments[i], true);\\n }\\n\\n signaturesRequired = newSigRequired;\\n }\\n\\n function removeSigners(uint256[] calldata commitmentsToRemove, uint256 newSigRequired) public onlySelf {\\n require(commitmentsToRemove.length > 0, \\\"Empty array\\\");\\n require(commitments.length > commitmentsToRemove.length, \\\"Cannot remove all signers\\\");\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length - commitmentsToRemove.length, \\\"Sigs required too high\\\");\\n\\n for (uint256 i = 0; i < commitmentsToRemove.length; i++) {\\n bool found = false;\\n for (uint256 j = 0; j < commitments.length; j++) {\\n if (commitments[j] == commitmentsToRemove[i]) {\\n commitments[j] = commitments[commitments.length - 1];\\n commitments.pop();\\n found = true;\\n emit Owner(commitmentsToRemove[i], false);\\n break;\\n }\\n }\\n require(found, \\\"Commitment not found\\\");\\n }\\n\\n signaturesRequired = newSigRequired;\\n }\\n\\n function updateSignaturesRequired(uint256 newSigRequired) public onlySelf {\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length, \\\"Sigs required too high\\\");\\n signaturesRequired = newSigRequired;\\n }\\n\\n /**\\n * @notice Execute multiple transfers in one transaction\\n * @param recipients Array of recipient addresses\\n * @param amounts Array of amounts to send\\n */\\n function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) public onlySelf {\\n require(recipients.length == amounts.length, \\\"Length mismatch\\\");\\n require(recipients.length > 0, \\\"Empty batch\\\");\\n\\n for (uint256 i = 0; i < recipients.length; i++) {\\n require(recipients[i] != address(0), \\\"Invalid recipient\\\");\\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\\\"\\\");\\n require(success, \\\"Transfer failed\\\");\\n }\\n }\\n\\n /**\\n * @notice Execute multiple transfers with mixed token types\\n * @param recipients Array of recipient addresses\\n * @param amounts Array of amounts to send\\n * @param tokenAddresses Array of token addresses (address(0) = native ETH)\\n */\\n function batchTransferMulti(\\n address[] calldata recipients,\\n uint256[] calldata amounts,\\n address[] calldata tokenAddresses\\n ) public onlySelf {\\n require(recipients.length == amounts.length, \\\"Length mismatch\\\");\\n require(recipients.length == tokenAddresses.length, \\\"Length mismatch\\\");\\n require(recipients.length > 0, \\\"Empty batch\\\");\\n\\n for (uint256 i = 0; i < recipients.length; i++) {\\n require(recipients[i] != address(0), \\\"Invalid recipient\\\");\\n\\n if (tokenAddresses[i] == address(0)) {\\n // Native ETH transfer\\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\\\"\\\");\\n require(success, \\\"ETH transfer failed\\\");\\n } else {\\n // ERC20 transfer\\n (bool success, bytes memory data) = tokenAddresses[i].call(\\n abi.encodeWithSignature(\\\"transfer(address,uint256)\\\", recipients[i], amounts[i])\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"ERC20 transfer failed\\\");\\n }\\n }\\n }\\n\\n // ============ View Functions ============\\n function getTransactionHash(\\n uint256 _nonce,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) public view returns (bytes32) {\\n return keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\\n }\\n\\n function getCommitments() external view returns (uint256[] memory) {\\n return commitments;\\n }\\n\\n function getSignersCount() external view returns (uint256) {\\n return commitments.length;\\n }\\n\\n // ============ Internal Functions ============\\n function _verifyProof(bytes32 txHash, ZkProof calldata proof) internal view returns (bool) {\\n uint256 txHashCommitment = poseidonHash2(uint256(txHash), 1);\\n\\n // Public inputs order: tx_hash_commitment, commitment, nullifier\\n bytes memory encodedInputs = abi.encodePacked(txHashCommitment, proof.commitment, proof.nullifier);\\n\\n bytes32 leaf = keccak256(abi.encodePacked(PROVING_SYSTEM_ID, vkHash, VERSION_HASH, keccak256(encodedInputs)));\\n\\n return\\n IVerifyProofAggregation(zkvContract).verifyProofAggregation(\\n proof.domainId,\\n proof.aggregationId,\\n leaf,\\n proof.zkMerklePath,\\n proof.leafCount,\\n proof.index\\n );\\n }\\n\\n function _isCurrentSigner(uint256 commitment) internal view returns (bool) {\\n for (uint256 i = 0; i < commitments.length; i++) {\\n if (commitments[i] == commitment) {\\n return true;\\n }\\n }\\n return false;\\n }\\n\\n // ============ Receive ETH ============\\n receive() external payable {\\n emit Deposit(msg.sender, msg.value, address(this).balance);\\n }\\n\\n function poseidonHash2(uint256 a, uint256 b) public pure returns (uint256) {\\n uint256 safeA = a % BN254_PRIME;\\n uint256 safeB = b % BN254_PRIME;\\n return PoseidonT3.hash([safeA, safeB]);\\n }\\n}\",\"keccak256\":\"0x0b7ce172ac16abad23b0d8197e2199c6953074d0879a156e0a4f08418c17c6cb\",\"license\":\"MIT\"},\"poseidon-solidity/PoseidonT3.sol\":{\"content\":\"/// SPDX-License-Identifier: MIT\\npragma solidity >=0.7.0;\\n\\nlibrary PoseidonT3 {\\n uint constant M00 = 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b;\\n uint constant M01 = 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771;\\n uint constant M02 = 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7;\\n uint constant M10 = 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0;\\n uint constant M11 = 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23;\\n uint constant M12 = 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911;\\n\\n // See here for a simplified implementation: https://github.com/vimwitch/poseidon-solidity/blob/e57becdabb65d99fdc586fe1e1e09e7108202d53/contracts/Poseidon.sol#L40\\n // Inspired by: https://github.com/iden3/circomlibjs/blob/v0.0.8/src/poseidon_slow.js\\n function hash(uint[2] memory) public pure returns (uint) {\\n assembly {\\n let F := 21888242871839275222246405745257275088548364400416034343698204186575808495617\\n let M20 := 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d\\n let M21 := 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa\\n let M22 := 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0\\n\\n // load the inputs from memory\\n let state1 := add(mod(mload(0x80), F), 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864)\\n let state2 := add(mod(mload(0xa0), F), 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5)\\n let scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(\\n 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0,\\n add(add(15452833169820924772166449970675545095234312153403844297388521437673434406763, mulmod(state1, M10, F)), mulmod(state2, M20, F))\\n )\\n let scratch1 := add(\\n 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2,\\n add(add(18674271267752038776579386132900109523609358935013267566297499497165104279117, mulmod(state1, M11, F)), mulmod(state2, M21, F))\\n )\\n let scratch2 := add(\\n 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa,\\n add(add(14817777843080276494683266178512808687156649753153012854386334860566696099579, mulmod(state1, M12, F)), mulmod(state2, M22, F))\\n )\\n let state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n\\n mstore(0x0, mod(add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)), F))\\n\\n return(0, 0x20)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0102caa303bbc6690508f3615604f7730789ed990058c9513a87ccb30e4835be\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b50604051620024a0380380620024a08339810160408190526200003491620002db565b6001600160a01b038516620000905760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207a6b7620616464726573730000000000000000000000000060448201526064015b60405180910390fd5b60008111620000e25760405162461bcd60e51b815260206004820152601e60248201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604482015260640162000087565b6000825111620001355760405162461bcd60e51b815260206004820152601660248201527f4e656564206174206c656173742031207369676e657200000000000000000000604482015260640162000087565b8151811115620001885760405162461bcd60e51b815260206004820152601660248201527f5369677320726571756972656420746f6f206869676800000000000000000000604482015260640162000087565b6001600160a01b03851660805260a0849052600083815560018290555b8251811015620002b957828181518110620001c457620001c4620003e6565b6020026020010151600003620002125760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b604482015260640162000087565b6002838281518110620002295762000229620003e6565b6020908102919091018101518254600181018455600093845291909220015582518390829081106200025f576200025f620003e6565b60200260200101517f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d60016040516200029c911515815260200190565b60405180910390a280620002b081620003fc565b915050620001a5565b50505050505062000424565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620002f457600080fd5b85516001600160a01b03811681146200030c57600080fd5b602087810151604089015160608a01519398509096509450906001600160401b03808211156200033b57600080fd5b818901915089601f8301126200035057600080fd5b815181811115620003655762000365620002c5565b8060051b604051601f19603f830116810181811085821117156200038d576200038d620002c5565b60405291825284820192508381018501918c831115620003ac57600080fd5b938501935b82851015620003cc57845184529385019392850192620003b1565b809750505050505050608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6000600182016200041d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516120486200045860003960008181610221015261167b0152600081816102d5015261173301526120486000f3fe6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d1578063ce757d2914610401578063e4cf5a2c14610417578063eaaba5591461044b578063f1ea66d41461046b57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b157600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b5061018961018436600461185a565b61048d565b604051610196919061196c565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611986565b610835565b005b3480156101cd57600080fd5b506101bf6101dc36600461199f565b61089b565b3480156101ed57600080fd5b506102016101fc366004611986565b610b29565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e366004611a01565b610b4a565b34801561026f57600080fd5b506101bf61027e366004611ad6565b610b87565b34801561028f57600080fd5b506102b361029e366004611986565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b70565b610f44565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611128565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405169756c747261706c6f6e6b60b01b6020820152602a016040516020818303038152906040528051906020012081565b3480156103bd57600080fd5b506101bf6103cc36600461199f565b611188565b3480156103dd57600080fd5b506102b36103ec366004611986565b60046020526000908152604090205460ff1681565b34801561040d57600080fd5b5061020160015481565b34801561042357600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045757600080fd5b50610201610466366004611bdc565b61145e565b34801561047757600080fd5b5061048061154f565b6040516101969190611bfe565b60008781526003602052604090205460609060ff16156104e95760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052f5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104e0565b6000805460405161054e9130918c908c908c908c908c90602001611c42565b60405160208183030381529060405280519060200120905060005b8381101561072f576004600086868481811061058757610587611c94565b90506020028101906105999190611caa565b60209081013582528101919091526040016000205460ff16156105f75760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104e0565b61062485858381811061060c5761060c611c94565b905060200281019061061e9190611caa565b356115a7565b6106675760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104e0565b6106948286868481811061067d5761067d611c94565b905060200281019061068f9190611caa565b6115fd565b6106d05760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104e0565b6001600460008787858181106106e8576106e8611c94565b90506020028101906106fa9190611caa565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072781611ce0565b915050610569565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610767908b908b90611cf9565b60006040518083038185875af1925050503d80600081146107a4576040519150601f19603f3d011682016040523d82523d6000602084013e6107a9565b606091505b5091509150816107e75760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104e0565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081f959493929190611d09565b60405180910390a29a9950505050505050505050565b3330146108545760405162461bcd60e51b81526004016104e090611d6a565b600081116108745760405162461bcd60e51b81526004016104e090611d8c565b6002548111156108965760405162461bcd60e51b81526004016104e090611dc3565b600155565b3330146108ba5760405162461bcd60e51b81526004016104e090611d6a565b816108f55760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b60025482106109465760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104e0565b600081116109665760405162461bcd60e51b81526004016104e090611d8c565b600254610974908390611df3565b8111156109935760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b21576000805b600254811015610ac9578585848181106109be576109be611c94565b90506020020135600282815481106109d8576109d8611c94565b906000526020600020015403610ab757600280546109f890600190611df3565b81548110610a0857610a08611c94565b906000526020600020015460028281548110610a2657610a26611c94565b6000918252602090912001556002805480610a4357610a43611e06565b6001900381819060005260206000200160009055905560019150858584818110610a6f57610a6f611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aaa911515815260200190565b60405180910390a2610ac9565b80610ac181611ce0565b9150506109a2565b5080610b0e5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104e0565b5080610b1981611ce0565b915050610996565b506001555050565b60028181548110610b3957600080fd5b600091825260209091200154905081565b60008054604051610b679130918890889088908890602001611e1c565b604051602081830303815290604052805190602001209050949350505050565b333014610ba65760405162461bcd60e51b81526004016104e090611d6a565b848314610bc55760405162461bcd60e51b81526004016104e090611e77565b848114610be45760405162461bcd60e51b81526004016104e090611e77565b84610c1f5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b85811015610f3b576000878783818110610c3e57610c3e611c94565b9050602002016020810190610c539190611ea0565b6001600160a01b031603610c9d5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b6000838383818110610cb157610cb1611c94565b9050602002016020810190610cc69190611ea0565b6001600160a01b031603610db1576000878783818110610ce857610ce8611c94565b9050602002016020810190610cfd9190611ea0565b6001600160a01b0316868684818110610d1857610d18611c94565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5f576040519150601f19603f3d011682016040523d82523d6000602084013e610d64565b606091505b5050905080610dab5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104e0565b50610f29565b600080848484818110610dc657610dc6611c94565b9050602002016020810190610ddb9190611ea0565b6001600160a01b0316898985818110610df657610df6611c94565b9050602002016020810190610e0b9190611ea0565b888886818110610e1d57610e1d611c94565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e769190611ebb565b6000604051808303816000865af19150503d8060008114610eb3576040519150601f19603f3d011682016040523d82523d6000602084013e610eb8565b606091505b5091509150818015610ee2575080511580610ee2575080806020019051810190610ee29190611ecd565b610f265760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104e0565b50505b80610f3381611ce0565b915050610c22565b50505050505050565b333014610f635760405162461bcd60e51b81526004016104e090611d6a565b828114610f825760405162461bcd60e51b81526004016104e090611e77565b82610fbd5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b83811015611121576000858583818110610fdc57610fdc611c94565b9050602002016020810190610ff19190611ea0565b6001600160a01b03160361103b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b600085858381811061104f5761104f611c94565b90506020020160208101906110649190611ea0565b6001600160a01b031684848481811061107f5761107f611c94565b9050602002013560405160006040518083038185875af1925050503d80600081146110c6576040519150601f19603f3d011682016040523d82523d6000602084013e6110cb565b606091505b505090508061110e5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104e0565b508061111981611ce0565b915050610fc0565b5050505050565b604080516000815260208101918290526002916111459190611ebb565b602060405180830381855afa158015611162573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111859190611eef565b81565b3330146111a75760405162461bcd60e51b81526004016104e090611d6a565b816111e25760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b600081116112025760405162461bcd60e51b81526004016104e090611d8c565b600254611210908390611f08565b81111561122f5760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b215783838281811061124c5761124c611c94565b905060200201356000036112975760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104e0565b60005b60025481101561132e578484838181106112b6576112b6611c94565b90506020020135600282815481106112d0576112d0611c94565b90600052602060002001540361131c5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104e0565b8061132681611ce0565b91505061129a565b5060005b818110156113c05784848381811061134c5761134c611c94565b9050602002013585858381811061136557611365611c94565b90506020020135036113ae5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104e0565b806113b881611ce0565b915050611332565b5060028484838181106113d5576113d5611c94565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140957611409611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611444911515815260200190565b60405180910390a28061145681611ce0565b915050611232565b60008061148b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b905060006114b97f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b604080518082018252848152602081018390529051632b0aac7f60e11b8152919250733333333C0A88F9BE4fd23ed0536F9B6c427e3B939163561558fe9161150391600401611f3d565b602060405180830381865af4158015611520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115449190611eef565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159d57602002820191906000526020600020905b815481526020019060010190808311611589575b5050505050905090565b6000805b6002548110156115f45782600282815481106115c9576115c9611c94565b9060005260206000200154036115e25750600192915050565b806115ec81611ce0565b9150506115ab565b50600092915050565b60008061160b84600161145e565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845269756c747261706c6f6e6b60b01b60a08401528351608a81850301815260aa840180865281519190930120600080845260ca909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a89190611ebb565b602060405180830381855afa1580156116c5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e89190611eef565b8480519060200120604051602001611719949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e36866060013587604001358489806080019061177b9190611f6e565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a79796959493929190611fb8565b602060405180830381865afa1580156117c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e89190611ecd565b9695505050505050565b80356001600160a01b038116811461180957600080fd5b919050565b60008083601f84011261182057600080fd5b50813567ffffffffffffffff81111561183857600080fd5b6020830191508360208260051b850101111561185357600080fd5b9250929050565b600080600080600080600060a0888a03121561187557600080fd5b87359650611885602089016117f2565b955060408801359450606088013567ffffffffffffffff808211156118a957600080fd5b818a0191508a601f8301126118bd57600080fd5b8135818111156118cc57600080fd5b8b60208285010111156118de57600080fd5b6020830196508095505060808a01359150808211156118fc57600080fd5b506119098a828b0161180e565b989b979a50959850939692959293505050565b60005b8381101561193757818101518382015260200161191f565b50506000910152565b6000815180845261195881602086016020860161191c565b601f01601f19169290920160200192915050565b60208152600061197f6020830184611940565b9392505050565b60006020828403121561199857600080fd5b5035919050565b6000806000604084860312156119b457600080fd5b833567ffffffffffffffff8111156119cb57600080fd5b6119d78682870161180e565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1757600080fd5b84359350611a27602086016117f2565b925060408501359150606085013567ffffffffffffffff80821115611a4b57600080fd5b818701915087601f830112611a5f57600080fd5b813581811115611a7157611a716119eb565b604051601f8201601f19908116603f01168101908382118183101715611a9957611a996119eb565b816040528281528a6020848701011115611ab257600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aef57600080fd5b863567ffffffffffffffff80821115611b0757600080fd5b611b138a838b0161180e565b90985096506020890135915080821115611b2c57600080fd5b611b388a838b0161180e565b90965094506040890135915080821115611b5157600080fd5b50611b5e89828a0161180e565b979a9699509497509295939492505050565b60008060008060408587031215611b8657600080fd5b843567ffffffffffffffff80821115611b9e57600080fd5b611baa8883890161180e565b90965094506020870135915080821115611bc357600080fd5b50611bd08782880161180e565b95989497509550505050565b60008060408385031215611bef57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3657835183529284019291840191600101611c1a565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cc057600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf257611cf2611cca565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5e60a0820185611940565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154957611549611cca565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6581608885016020870161191c565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb257600080fd5b61197f826117f2565b60008251611cc081846020870161191c565b600060208284031215611edf57600080fd5b8151801515811461197f57600080fd5b600060208284031215611f0157600080fd5b5051919050565b8082018082111561154957611549611cca565b600082611f3857634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f65578151835260209283019290910190600101611f46565b50505092915050565b6000808335601e19843603018112611f8557600080fd5b83018035915067ffffffffffffffff821115611fa057600080fd5b6020019150600581901b360382131561185357600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe957600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea2646970667358221220925328ba1cb1d89f7ed11053888b9080bbb4027159fb1003d3575f3e6578fd1464736f6c63430008140033", - "deployedBytecode": "0x6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d1578063ce757d2914610401578063e4cf5a2c14610417578063eaaba5591461044b578063f1ea66d41461046b57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b157600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b5061018961018436600461185a565b61048d565b604051610196919061196c565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611986565b610835565b005b3480156101cd57600080fd5b506101bf6101dc36600461199f565b61089b565b3480156101ed57600080fd5b506102016101fc366004611986565b610b29565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e366004611a01565b610b4a565b34801561026f57600080fd5b506101bf61027e366004611ad6565b610b87565b34801561028f57600080fd5b506102b361029e366004611986565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b70565b610f44565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611128565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405169756c747261706c6f6e6b60b01b6020820152602a016040516020818303038152906040528051906020012081565b3480156103bd57600080fd5b506101bf6103cc36600461199f565b611188565b3480156103dd57600080fd5b506102b36103ec366004611986565b60046020526000908152604090205460ff1681565b34801561040d57600080fd5b5061020160015481565b34801561042357600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045757600080fd5b50610201610466366004611bdc565b61145e565b34801561047757600080fd5b5061048061154f565b6040516101969190611bfe565b60008781526003602052604090205460609060ff16156104e95760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052f5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104e0565b6000805460405161054e9130918c908c908c908c908c90602001611c42565b60405160208183030381529060405280519060200120905060005b8381101561072f576004600086868481811061058757610587611c94565b90506020028101906105999190611caa565b60209081013582528101919091526040016000205460ff16156105f75760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104e0565b61062485858381811061060c5761060c611c94565b905060200281019061061e9190611caa565b356115a7565b6106675760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104e0565b6106948286868481811061067d5761067d611c94565b905060200281019061068f9190611caa565b6115fd565b6106d05760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104e0565b6001600460008787858181106106e8576106e8611c94565b90506020028101906106fa9190611caa565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072781611ce0565b915050610569565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610767908b908b90611cf9565b60006040518083038185875af1925050503d80600081146107a4576040519150601f19603f3d011682016040523d82523d6000602084013e6107a9565b606091505b5091509150816107e75760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104e0565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081f959493929190611d09565b60405180910390a29a9950505050505050505050565b3330146108545760405162461bcd60e51b81526004016104e090611d6a565b600081116108745760405162461bcd60e51b81526004016104e090611d8c565b6002548111156108965760405162461bcd60e51b81526004016104e090611dc3565b600155565b3330146108ba5760405162461bcd60e51b81526004016104e090611d6a565b816108f55760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b60025482106109465760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104e0565b600081116109665760405162461bcd60e51b81526004016104e090611d8c565b600254610974908390611df3565b8111156109935760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b21576000805b600254811015610ac9578585848181106109be576109be611c94565b90506020020135600282815481106109d8576109d8611c94565b906000526020600020015403610ab757600280546109f890600190611df3565b81548110610a0857610a08611c94565b906000526020600020015460028281548110610a2657610a26611c94565b6000918252602090912001556002805480610a4357610a43611e06565b6001900381819060005260206000200160009055905560019150858584818110610a6f57610a6f611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aaa911515815260200190565b60405180910390a2610ac9565b80610ac181611ce0565b9150506109a2565b5080610b0e5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104e0565b5080610b1981611ce0565b915050610996565b506001555050565b60028181548110610b3957600080fd5b600091825260209091200154905081565b60008054604051610b679130918890889088908890602001611e1c565b604051602081830303815290604052805190602001209050949350505050565b333014610ba65760405162461bcd60e51b81526004016104e090611d6a565b848314610bc55760405162461bcd60e51b81526004016104e090611e77565b848114610be45760405162461bcd60e51b81526004016104e090611e77565b84610c1f5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b85811015610f3b576000878783818110610c3e57610c3e611c94565b9050602002016020810190610c539190611ea0565b6001600160a01b031603610c9d5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b6000838383818110610cb157610cb1611c94565b9050602002016020810190610cc69190611ea0565b6001600160a01b031603610db1576000878783818110610ce857610ce8611c94565b9050602002016020810190610cfd9190611ea0565b6001600160a01b0316868684818110610d1857610d18611c94565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5f576040519150601f19603f3d011682016040523d82523d6000602084013e610d64565b606091505b5050905080610dab5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104e0565b50610f29565b600080848484818110610dc657610dc6611c94565b9050602002016020810190610ddb9190611ea0565b6001600160a01b0316898985818110610df657610df6611c94565b9050602002016020810190610e0b9190611ea0565b888886818110610e1d57610e1d611c94565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e769190611ebb565b6000604051808303816000865af19150503d8060008114610eb3576040519150601f19603f3d011682016040523d82523d6000602084013e610eb8565b606091505b5091509150818015610ee2575080511580610ee2575080806020019051810190610ee29190611ecd565b610f265760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104e0565b50505b80610f3381611ce0565b915050610c22565b50505050505050565b333014610f635760405162461bcd60e51b81526004016104e090611d6a565b828114610f825760405162461bcd60e51b81526004016104e090611e77565b82610fbd5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b83811015611121576000858583818110610fdc57610fdc611c94565b9050602002016020810190610ff19190611ea0565b6001600160a01b03160361103b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b600085858381811061104f5761104f611c94565b90506020020160208101906110649190611ea0565b6001600160a01b031684848481811061107f5761107f611c94565b9050602002013560405160006040518083038185875af1925050503d80600081146110c6576040519150601f19603f3d011682016040523d82523d6000602084013e6110cb565b606091505b505090508061110e5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104e0565b508061111981611ce0565b915050610fc0565b5050505050565b604080516000815260208101918290526002916111459190611ebb565b602060405180830381855afa158015611162573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111859190611eef565b81565b3330146111a75760405162461bcd60e51b81526004016104e090611d6a565b816111e25760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b600081116112025760405162461bcd60e51b81526004016104e090611d8c565b600254611210908390611f08565b81111561122f5760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b215783838281811061124c5761124c611c94565b905060200201356000036112975760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104e0565b60005b60025481101561132e578484838181106112b6576112b6611c94565b90506020020135600282815481106112d0576112d0611c94565b90600052602060002001540361131c5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104e0565b8061132681611ce0565b91505061129a565b5060005b818110156113c05784848381811061134c5761134c611c94565b9050602002013585858381811061136557611365611c94565b90506020020135036113ae5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104e0565b806113b881611ce0565b915050611332565b5060028484838181106113d5576113d5611c94565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140957611409611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611444911515815260200190565b60405180910390a28061145681611ce0565b915050611232565b60008061148b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b905060006114b97f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b604080518082018252848152602081018390529051632b0aac7f60e11b815291925073__$75f79a42d9bcbdbb69ad79ebd80f556f39$__9163561558fe9161150391600401611f3d565b602060405180830381865af4158015611520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115449190611eef565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159d57602002820191906000526020600020905b815481526020019060010190808311611589575b5050505050905090565b6000805b6002548110156115f45782600282815481106115c9576115c9611c94565b9060005260206000200154036115e25750600192915050565b806115ec81611ce0565b9150506115ab565b50600092915050565b60008061160b84600161145e565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845269756c747261706c6f6e6b60b01b60a08401528351608a81850301815260aa840180865281519190930120600080845260ca909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a89190611ebb565b602060405180830381855afa1580156116c5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e89190611eef565b8480519060200120604051602001611719949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e36866060013587604001358489806080019061177b9190611f6e565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a79796959493929190611fb8565b602060405180830381865afa1580156117c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e89190611ecd565b9695505050505050565b80356001600160a01b038116811461180957600080fd5b919050565b60008083601f84011261182057600080fd5b50813567ffffffffffffffff81111561183857600080fd5b6020830191508360208260051b850101111561185357600080fd5b9250929050565b600080600080600080600060a0888a03121561187557600080fd5b87359650611885602089016117f2565b955060408801359450606088013567ffffffffffffffff808211156118a957600080fd5b818a0191508a601f8301126118bd57600080fd5b8135818111156118cc57600080fd5b8b60208285010111156118de57600080fd5b6020830196508095505060808a01359150808211156118fc57600080fd5b506119098a828b0161180e565b989b979a50959850939692959293505050565b60005b8381101561193757818101518382015260200161191f565b50506000910152565b6000815180845261195881602086016020860161191c565b601f01601f19169290920160200192915050565b60208152600061197f6020830184611940565b9392505050565b60006020828403121561199857600080fd5b5035919050565b6000806000604084860312156119b457600080fd5b833567ffffffffffffffff8111156119cb57600080fd5b6119d78682870161180e565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1757600080fd5b84359350611a27602086016117f2565b925060408501359150606085013567ffffffffffffffff80821115611a4b57600080fd5b818701915087601f830112611a5f57600080fd5b813581811115611a7157611a716119eb565b604051601f8201601f19908116603f01168101908382118183101715611a9957611a996119eb565b816040528281528a6020848701011115611ab257600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aef57600080fd5b863567ffffffffffffffff80821115611b0757600080fd5b611b138a838b0161180e565b90985096506020890135915080821115611b2c57600080fd5b611b388a838b0161180e565b90965094506040890135915080821115611b5157600080fd5b50611b5e89828a0161180e565b979a9699509497509295939492505050565b60008060008060408587031215611b8657600080fd5b843567ffffffffffffffff80821115611b9e57600080fd5b611baa8883890161180e565b90965094506020870135915080821115611bc357600080fd5b50611bd08782880161180e565b95989497509550505050565b60008060408385031215611bef57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3657835183529284019291840191600101611c1a565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cc057600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf257611cf2611cca565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5e60a0820185611940565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154957611549611cca565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6581608885016020870161191c565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb257600080fd5b61197f826117f2565b60008251611cc081846020870161191c565b600060208284031215611edf57600080fd5b8151801515811461197f57600080fd5b600060208284031215611f0157600080fd5b5051919050565b8082018082111561154957611549611cca565b600082611f3857634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f65578151835260209283019290910190600101611f46565b50505092915050565b6000808335601e19843603018112611f8557600080fd5b83018035915067ffffffffffffffff821115611fa057600080fd5b6020019150600581901b360382131561185357600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe957600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea2646970667358221220925328ba1cb1d89f7ed11053888b9080bbb4027159fb1003d3575f3e6578fd1464736f6c63430008140033", + "numDeployments": 2, + "solcInputHash": "10833bafee6b78acc8e4896ca53dfe58", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_zkvContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_vkHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"_initialCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_signaturesRequired\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"commitment\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isAdded\",\"type\":\"bool\"}],\"name\":\"Owner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"name\":\"TransactionExecuted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BN254_PRIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVING_SYSTEM_ID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION_HASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"newCommitments\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"addSigners\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"batchTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"address[]\",\"name\":\"tokenAddresses\",\"type\":\"address[]\"}],\"name\":\"batchTransferMulti\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"commitments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"commitment\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nullifier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"aggregationId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"domainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"zkMerklePath\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"internalType\":\"struct MetaMultiSigWallet.ZkProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCommitments\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSignersCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getTransactionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"name\":\"poseidonHash2\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"commitmentsToRemove\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"removeSigners\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"signaturesRequired\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newSigRequired\",\"type\":\"uint256\"}],\"name\":\"updateSignaturesRequired\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedNonces\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedNullifiers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vkHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zkvContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"batchTransfer(address[],uint256[])\":{\"params\":{\"amounts\":\"Array of amounts to send\",\"recipients\":\"Array of recipient addresses\"}},\"batchTransferMulti(address[],uint256[],address[])\":{\"params\":{\"amounts\":\"Array of amounts to send\",\"recipients\":\"Array of recipient addresses\",\"tokenAddresses\":\"Array of token addresses (address(0) = native ETH)\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"batchTransfer(address[],uint256[])\":{\"notice\":\"Execute multiple transfers in one transaction\"},\"batchTransferMulti(address[],uint256[],address[])\":{\"notice\":\"Execute multiple transfers with mixed token types\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MetaMultiSigWallet.sol\":\"MetaMultiSigWallet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/MetaMultiSigWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport \\\"poseidon-solidity/PoseidonT3.sol\\\";\\n\\ninterface IVerifyProofAggregation {\\n function verifyProofAggregation(\\n uint256 _domainId,\\n uint256 _aggregationId,\\n bytes32 _leaf,\\n bytes32[] calldata _merklePath,\\n uint256 _leafCount,\\n uint256 _index\\n ) external view returns (bool);\\n}\\n\\ncontract MetaMultiSigWallet {\\n // ============ Constants ============\\n bytes32 public constant PROVING_SYSTEM_ID = keccak256(abi.encodePacked(\\\"ultrahonk\\\"));\\n bytes32 public constant VERSION_HASH = sha256(abi.encodePacked(\\\"\\\"));\\n uint256 public constant BN254_PRIME = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\\n\\n // ============ Events ============\\n event Deposit(address indexed sender, uint256 amount, uint256 balance);\\n event TransactionExecuted(uint256 indexed nonce, address to, uint256 value, bytes data, bytes result);\\n event Owner(uint256 indexed commitment, bool isAdded);\\n\\n // ============ Structs ============\\n struct ZkProof {\\n uint256 commitment;\\n uint256 nullifier;\\n uint256 aggregationId;\\n uint256 domainId;\\n bytes32[] zkMerklePath;\\n uint256 leafCount;\\n uint256 index;\\n }\\n\\n // ============ State ============\\n address public immutable zkvContract;\\n bytes32 public immutable vkHash;\\n uint256 public chainId;\\n uint256 public signaturesRequired;\\n\\n // Signer management\\n uint256[] public commitments;\\n\\n // Nonce tracking (prevent replay)\\n mapping(uint256 => bool) public usedNonces;\\n\\n // Nullifier tracking (prevent double-signing)\\n mapping(uint256 => bool) public usedNullifiers;\\n\\n // ============ Constructor ============\\n constructor(\\n address _zkvContract,\\n bytes32 _vkHash,\\n uint256 _chainId,\\n uint256[] memory _initialCommitments,\\n uint256 _signaturesRequired\\n ) {\\n require(_zkvContract != address(0), \\\"Invalid zkv address\\\");\\n require(_signaturesRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(_initialCommitments.length > 0, \\\"Need at least 1 signer\\\");\\n require(_signaturesRequired <= _initialCommitments.length, \\\"Sigs required too high\\\");\\n\\n zkvContract = _zkvContract;\\n vkHash = _vkHash;\\n chainId = _chainId;\\n signaturesRequired = _signaturesRequired;\\n\\n for (uint256 i = 0; i < _initialCommitments.length; i++) {\\n require(_initialCommitments[i] != 0, \\\"Invalid commitment\\\");\\n commitments.push(_initialCommitments[i]);\\n emit Owner(_initialCommitments[i], true);\\n }\\n }\\n\\n // ============ Modifiers ============\\n modifier onlySelf() {\\n require(msg.sender == address(this), \\\"Not Self\\\");\\n _;\\n }\\n\\n // ============ Main Execute Function ============\\n function execute(\\n uint256 _nonce,\\n address to,\\n uint256 value,\\n bytes calldata data,\\n ZkProof[] calldata proofs\\n ) external returns (bytes memory) {\\n require(!usedNonces[_nonce], \\\"Nonce already used\\\");\\n require(proofs.length >= signaturesRequired, \\\"Not enough proofs\\\");\\n\\n bytes32 txHash = keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\\n\\n for (uint256 i = 0; i < proofs.length; i++) {\\n require(!usedNullifiers[proofs[i].nullifier], \\\"Nullifier already used\\\");\\n require(_isCurrentSigner(proofs[i].commitment), \\\"Not a current signer\\\");\\n require(_verifyProof(txHash, proofs[i]), \\\"Invalid proof\\\");\\n usedNullifiers[proofs[i].nullifier] = true;\\n }\\n\\n usedNonces[_nonce] = true;\\n\\n (bool success, bytes memory result) = to.call{ value: value }(data);\\n require(success, \\\"Tx failed\\\");\\n\\n emit TransactionExecuted(_nonce, to, value, data, result);\\n return result;\\n }\\n\\n // ============ Signer Management ============\\n function addSigners(uint256[] calldata newCommitments, uint256 newSigRequired) public onlySelf {\\n require(newCommitments.length > 0, \\\"Empty array\\\");\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length + newCommitments.length, \\\"Sigs required too high\\\");\\n\\n for (uint256 i = 0; i < newCommitments.length; i++) {\\n require(newCommitments[i] != 0, \\\"Invalid commitment\\\");\\n \\n // Check duplicate with existing signers\\n for (uint256 j = 0; j < commitments.length; j++) {\\n require(commitments[j] != newCommitments[i], \\\"Commitment exists\\\");\\n }\\n \\n // Check duplicate within input array\\n for (uint256 k = 0; k < i; k++) {\\n require(newCommitments[k] != newCommitments[i], \\\"Duplicate in input\\\");\\n }\\n\\n commitments.push(newCommitments[i]);\\n emit Owner(newCommitments[i], true);\\n }\\n\\n signaturesRequired = newSigRequired;\\n }\\n\\n function removeSigners(uint256[] calldata commitmentsToRemove, uint256 newSigRequired) public onlySelf {\\n require(commitmentsToRemove.length > 0, \\\"Empty array\\\");\\n require(commitments.length > commitmentsToRemove.length, \\\"Cannot remove all signers\\\");\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length - commitmentsToRemove.length, \\\"Sigs required too high\\\");\\n\\n for (uint256 i = 0; i < commitmentsToRemove.length; i++) {\\n bool found = false;\\n for (uint256 j = 0; j < commitments.length; j++) {\\n if (commitments[j] == commitmentsToRemove[i]) {\\n commitments[j] = commitments[commitments.length - 1];\\n commitments.pop();\\n found = true;\\n emit Owner(commitmentsToRemove[i], false);\\n break;\\n }\\n }\\n require(found, \\\"Commitment not found\\\");\\n }\\n\\n signaturesRequired = newSigRequired;\\n }\\n\\n function updateSignaturesRequired(uint256 newSigRequired) public onlySelf {\\n require(newSigRequired > 0, \\\"Must be non-zero sigs required\\\");\\n require(newSigRequired <= commitments.length, \\\"Sigs required too high\\\");\\n signaturesRequired = newSigRequired;\\n }\\n\\n /**\\n * @notice Execute multiple transfers in one transaction\\n * @param recipients Array of recipient addresses\\n * @param amounts Array of amounts to send\\n */\\n function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) public onlySelf {\\n require(recipients.length == amounts.length, \\\"Length mismatch\\\");\\n require(recipients.length > 0, \\\"Empty batch\\\");\\n\\n for (uint256 i = 0; i < recipients.length; i++) {\\n require(recipients[i] != address(0), \\\"Invalid recipient\\\");\\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\\\"\\\");\\n require(success, \\\"Transfer failed\\\");\\n }\\n }\\n\\n /**\\n * @notice Execute multiple transfers with mixed token types\\n * @param recipients Array of recipient addresses\\n * @param amounts Array of amounts to send\\n * @param tokenAddresses Array of token addresses (address(0) = native ETH)\\n */\\n function batchTransferMulti(\\n address[] calldata recipients,\\n uint256[] calldata amounts,\\n address[] calldata tokenAddresses\\n ) public onlySelf {\\n require(recipients.length == amounts.length, \\\"Length mismatch\\\");\\n require(recipients.length == tokenAddresses.length, \\\"Length mismatch\\\");\\n require(recipients.length > 0, \\\"Empty batch\\\");\\n\\n for (uint256 i = 0; i < recipients.length; i++) {\\n require(recipients[i] != address(0), \\\"Invalid recipient\\\");\\n\\n if (tokenAddresses[i] == address(0)) {\\n // Native ETH transfer\\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\\\"\\\");\\n require(success, \\\"ETH transfer failed\\\");\\n } else {\\n // ERC20 transfer\\n (bool success, bytes memory data) = tokenAddresses[i].call(\\n abi.encodeWithSignature(\\\"transfer(address,uint256)\\\", recipients[i], amounts[i])\\n );\\n require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"ERC20 transfer failed\\\");\\n }\\n }\\n }\\n\\n // ============ View Functions ============\\n function getTransactionHash(\\n uint256 _nonce,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) public view returns (bytes32) {\\n return keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\\n }\\n\\n function getCommitments() external view returns (uint256[] memory) {\\n return commitments;\\n }\\n\\n function getSignersCount() external view returns (uint256) {\\n return commitments.length;\\n }\\n\\n // ============ Internal Functions ============\\n function _verifyProof(bytes32 txHash, ZkProof calldata proof) internal view returns (bool) {\\n uint256 txHashCommitment = poseidonHash2(uint256(txHash), 1);\\n\\n // Public inputs order: tx_hash_commitment, commitment, nullifier\\n bytes memory encodedInputs = abi.encodePacked(txHashCommitment, proof.commitment, proof.nullifier);\\n\\n bytes32 leaf = keccak256(abi.encodePacked(PROVING_SYSTEM_ID, vkHash, VERSION_HASH, keccak256(encodedInputs)));\\n\\n return\\n IVerifyProofAggregation(zkvContract).verifyProofAggregation(\\n proof.domainId,\\n proof.aggregationId,\\n leaf,\\n proof.zkMerklePath,\\n proof.leafCount,\\n proof.index\\n );\\n }\\n\\n function _isCurrentSigner(uint256 commitment) internal view returns (bool) {\\n for (uint256 i = 0; i < commitments.length; i++) {\\n if (commitments[i] == commitment) {\\n return true;\\n }\\n }\\n return false;\\n }\\n\\n // ============ Receive ETH ============\\n receive() external payable {\\n emit Deposit(msg.sender, msg.value, address(this).balance);\\n }\\n\\n function poseidonHash2(uint256 a, uint256 b) public pure returns (uint256) {\\n uint256 safeA = a % BN254_PRIME;\\n uint256 safeB = b % BN254_PRIME;\\n return PoseidonT3.hash([safeA, safeB]);\\n }\\n}\",\"keccak256\":\"0x301322f9d9bc48c7d4819701c01a0ee5e9050b68a5111dcbb7bb417f203ae708\",\"license\":\"MIT\"},\"poseidon-solidity/PoseidonT3.sol\":{\"content\":\"/// SPDX-License-Identifier: MIT\\npragma solidity >=0.7.0;\\n\\nlibrary PoseidonT3 {\\n uint constant M00 = 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b;\\n uint constant M01 = 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771;\\n uint constant M02 = 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7;\\n uint constant M10 = 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0;\\n uint constant M11 = 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23;\\n uint constant M12 = 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911;\\n\\n // See here for a simplified implementation: https://github.com/vimwitch/poseidon-solidity/blob/e57becdabb65d99fdc586fe1e1e09e7108202d53/contracts/Poseidon.sol#L40\\n // Inspired by: https://github.com/iden3/circomlibjs/blob/v0.0.8/src/poseidon_slow.js\\n function hash(uint[2] memory) public pure returns (uint) {\\n assembly {\\n let F := 21888242871839275222246405745257275088548364400416034343698204186575808495617\\n let M20 := 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d\\n let M21 := 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa\\n let M22 := 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0\\n\\n // load the inputs from memory\\n let state1 := add(mod(mload(0x80), F), 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864)\\n let state2 := add(mod(mload(0xa0), F), 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5)\\n let scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(\\n 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0,\\n add(add(15452833169820924772166449970675545095234312153403844297388521437673434406763, mulmod(state1, M10, F)), mulmod(state2, M20, F))\\n )\\n let scratch1 := add(\\n 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2,\\n add(add(18674271267752038776579386132900109523609358935013267566297499497165104279117, mulmod(state1, M11, F)), mulmod(state2, M21, F))\\n )\\n let scratch2 := add(\\n 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa,\\n add(add(14817777843080276494683266178512808687156649753153012854386334860566696099579, mulmod(state1, M12, F)), mulmod(state2, M22, F))\\n )\\n let state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := add(0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := add(0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n scratch0 := add(0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\\n scratch1 := add(0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\\n scratch2 := add(0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\\n state0 := mulmod(scratch0, scratch0, F)\\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\\n state0 := mulmod(scratch1, scratch1, F)\\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\\n state0 := mulmod(scratch2, scratch2, F)\\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\\n state0 := add(0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\\n state1 := add(0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\\n state2 := add(0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\\n scratch0 := mulmod(state0, state0, F)\\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\\n scratch0 := mulmod(state1, state1, F)\\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\\n scratch0 := mulmod(state2, state2, F)\\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\\n\\n mstore(0x0, mod(add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)), F))\\n\\n return(0, 0x20)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0102caa303bbc6690508f3615604f7730789ed990058c9513a87ccb30e4835be\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200249e3803806200249e8339810160408190526200003491620002db565b6001600160a01b038516620000905760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207a6b7620616464726573730000000000000000000000000060448201526064015b60405180910390fd5b60008111620000e25760405162461bcd60e51b815260206004820152601e60248201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604482015260640162000087565b6000825111620001355760405162461bcd60e51b815260206004820152601660248201527f4e656564206174206c656173742031207369676e657200000000000000000000604482015260640162000087565b8151811115620001885760405162461bcd60e51b815260206004820152601660248201527f5369677320726571756972656420746f6f206869676800000000000000000000604482015260640162000087565b6001600160a01b03851660805260a0849052600083815560018290555b8251811015620002b957828181518110620001c457620001c4620003e6565b6020026020010151600003620002125760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b604482015260640162000087565b6002838281518110620002295762000229620003e6565b6020908102919091018101518254600181018455600093845291909220015582518390829081106200025f576200025f620003e6565b60200260200101517f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d60016040516200029c911515815260200190565b60405180910390a280620002b081620003fc565b915050620001a5565b50505050505062000424565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620002f457600080fd5b85516001600160a01b03811681146200030c57600080fd5b602087810151604089015160608a01519398509096509450906001600160401b03808211156200033b57600080fd5b818901915089601f8301126200035057600080fd5b815181811115620003655762000365620002c5565b8060051b604051601f19603f830116810181811085821117156200038d576200038d620002c5565b60405291825284820192508381018501918c831115620003ac57600080fd5b938501935b82851015620003cc57845184529385019392850192620003b1565b809750505050505050608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6000600182016200041d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051612046620004586000396000818161022101526116790152600081816102d5015261173101526120466000f3fe6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d0578063ce757d2914610400578063e4cf5a2c14610416578063eaaba5591461044a578063f1ea66d41461046a57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b057600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b50610189610184366004611858565b61048c565b604051610196919061196a565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611984565b610834565b005b3480156101cd57600080fd5b506101bf6101dc36600461199d565b61089a565b3480156101ed57600080fd5b506102016101fc366004611984565b610b28565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e3660046119ff565b610b49565b34801561026f57600080fd5b506101bf61027e366004611ad4565b610b86565b34801561028f57600080fd5b506102b361029e366004611984565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b6e565b610f43565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611127565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405168756c747261686f6e6b60b81b60208201526029016040516020818303038152906040528051906020012081565b3480156103bc57600080fd5b506101bf6103cb36600461199d565b611187565b3480156103dc57600080fd5b506102b36103eb366004611984565b60046020526000908152604090205460ff1681565b34801561040c57600080fd5b5061020160015481565b34801561042257600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045657600080fd5b50610201610465366004611bda565b61145d565b34801561047657600080fd5b5061047f61154e565b6040516101969190611bfc565b60008781526003602052604090205460609060ff16156104e85760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052e5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104df565b6000805460405161054d9130918c908c908c908c908c90602001611c40565b60405160208183030381529060405280519060200120905060005b8381101561072e576004600086868481811061058657610586611c92565b90506020028101906105989190611ca8565b60209081013582528101919091526040016000205460ff16156105f65760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104df565b61062385858381811061060b5761060b611c92565b905060200281019061061d9190611ca8565b356115a6565b6106665760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104df565b6106938286868481811061067c5761067c611c92565b905060200281019061068e9190611ca8565b6115fc565b6106cf5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104df565b6001600460008787858181106106e7576106e7611c92565b90506020028101906106f99190611ca8565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072681611cde565b915050610568565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610766908b908b90611cf7565b60006040518083038185875af1925050503d80600081146107a3576040519150601f19603f3d011682016040523d82523d6000602084013e6107a8565b606091505b5091509150816107e65760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104df565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081e959493929190611d07565b60405180910390a29a9950505050505050505050565b3330146108535760405162461bcd60e51b81526004016104df90611d68565b600081116108735760405162461bcd60e51b81526004016104df90611d8a565b6002548111156108955760405162461bcd60e51b81526004016104df90611dc1565b600155565b3330146108b95760405162461bcd60e51b81526004016104df90611d68565b816108f45760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b60025482106109455760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104df565b600081116109655760405162461bcd60e51b81526004016104df90611d8a565b600254610973908390611df1565b8111156109925760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b20576000805b600254811015610ac8578585848181106109bd576109bd611c92565b90506020020135600282815481106109d7576109d7611c92565b906000526020600020015403610ab657600280546109f790600190611df1565b81548110610a0757610a07611c92565b906000526020600020015460028281548110610a2557610a25611c92565b6000918252602090912001556002805480610a4257610a42611e04565b6001900381819060005260206000200160009055905560019150858584818110610a6e57610a6e611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aa9911515815260200190565b60405180910390a2610ac8565b80610ac081611cde565b9150506109a1565b5080610b0d5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104df565b5080610b1881611cde565b915050610995565b506001555050565b60028181548110610b3857600080fd5b600091825260209091200154905081565b60008054604051610b669130918890889088908890602001611e1a565b604051602081830303815290604052805190602001209050949350505050565b333014610ba55760405162461bcd60e51b81526004016104df90611d68565b848314610bc45760405162461bcd60e51b81526004016104df90611e75565b848114610be35760405162461bcd60e51b81526004016104df90611e75565b84610c1e5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b85811015610f3a576000878783818110610c3d57610c3d611c92565b9050602002016020810190610c529190611e9e565b6001600160a01b031603610c9c5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b6000838383818110610cb057610cb0611c92565b9050602002016020810190610cc59190611e9e565b6001600160a01b031603610db0576000878783818110610ce757610ce7611c92565b9050602002016020810190610cfc9190611e9e565b6001600160a01b0316868684818110610d1757610d17611c92565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5e576040519150601f19603f3d011682016040523d82523d6000602084013e610d63565b606091505b5050905080610daa5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104df565b50610f28565b600080848484818110610dc557610dc5611c92565b9050602002016020810190610dda9190611e9e565b6001600160a01b0316898985818110610df557610df5611c92565b9050602002016020810190610e0a9190611e9e565b888886818110610e1c57610e1c611c92565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e759190611eb9565b6000604051808303816000865af19150503d8060008114610eb2576040519150601f19603f3d011682016040523d82523d6000602084013e610eb7565b606091505b5091509150818015610ee1575080511580610ee1575080806020019051810190610ee19190611ecb565b610f255760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104df565b50505b80610f3281611cde565b915050610c21565b50505050505050565b333014610f625760405162461bcd60e51b81526004016104df90611d68565b828114610f815760405162461bcd60e51b81526004016104df90611e75565b82610fbc5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b83811015611120576000858583818110610fdb57610fdb611c92565b9050602002016020810190610ff09190611e9e565b6001600160a01b03160361103a5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b600085858381811061104e5761104e611c92565b90506020020160208101906110639190611e9e565b6001600160a01b031684848481811061107e5761107e611c92565b9050602002013560405160006040518083038185875af1925050503d80600081146110c5576040519150601f19603f3d011682016040523d82523d6000602084013e6110ca565b606091505b505090508061110d5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104df565b508061111881611cde565b915050610fbf565b5050505050565b604080516000815260208101918290526002916111449190611eb9565b602060405180830381855afa158015611161573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111849190611eed565b81565b3330146111a65760405162461bcd60e51b81526004016104df90611d68565b816111e15760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b600081116112015760405162461bcd60e51b81526004016104df90611d8a565b60025461120f908390611f06565b81111561122e5760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b205783838281811061124b5761124b611c92565b905060200201356000036112965760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104df565b60005b60025481101561132d578484838181106112b5576112b5611c92565b90506020020135600282815481106112cf576112cf611c92565b90600052602060002001540361131b5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104df565b8061132581611cde565b915050611299565b5060005b818110156113bf5784848381811061134b5761134b611c92565b9050602002013585858381811061136457611364611c92565b90506020020135036113ad5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104df565b806113b781611cde565b915050611331565b5060028484838181106113d4576113d4611c92565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140857611408611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611443911515815260200190565b60405180910390a28061145581611cde565b915050611231565b60008061148a7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b905060006114b87f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b604080518082018252848152602081018390529051632b0aac7f60e11b8152919250733333333C0A88F9BE4fd23ed0536F9B6c427e3B939163561558fe9161150291600401611f3b565b602060405180830381865af415801561151f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115439190611eed565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159c57602002820191906000526020600020905b815481526020019060010190808311611588575b5050505050905090565b6000805b6002548110156115f35782600282815481106115c8576115c8611c92565b9060005260206000200154036115e15750600192915050565b806115eb81611cde565b9150506115aa565b50600092915050565b60008061160a84600161145d565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845268756c747261686f6e6b60b81b60a08401528351608981850301815260a9840180865281519190930120600080845260c9909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a69190611eb9565b602060405180830381855afa1580156116c3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e69190611eed565b8480519060200120604051602001611717949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e3686606001358760400135848980608001906117799190611f6c565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a59796959493929190611fb6565b602060405180830381865afa1580156117c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e69190611ecb565b9695505050505050565b80356001600160a01b038116811461180757600080fd5b919050565b60008083601f84011261181e57600080fd5b50813567ffffffffffffffff81111561183657600080fd5b6020830191508360208260051b850101111561185157600080fd5b9250929050565b600080600080600080600060a0888a03121561187357600080fd5b87359650611883602089016117f0565b955060408801359450606088013567ffffffffffffffff808211156118a757600080fd5b818a0191508a601f8301126118bb57600080fd5b8135818111156118ca57600080fd5b8b60208285010111156118dc57600080fd5b6020830196508095505060808a01359150808211156118fa57600080fd5b506119078a828b0161180c565b989b979a50959850939692959293505050565b60005b8381101561193557818101518382015260200161191d565b50506000910152565b6000815180845261195681602086016020860161191a565b601f01601f19169290920160200192915050565b60208152600061197d602083018461193e565b9392505050565b60006020828403121561199657600080fd5b5035919050565b6000806000604084860312156119b257600080fd5b833567ffffffffffffffff8111156119c957600080fd5b6119d58682870161180c565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1557600080fd5b84359350611a25602086016117f0565b925060408501359150606085013567ffffffffffffffff80821115611a4957600080fd5b818701915087601f830112611a5d57600080fd5b813581811115611a6f57611a6f6119e9565b604051601f8201601f19908116603f01168101908382118183101715611a9757611a976119e9565b816040528281528a6020848701011115611ab057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aed57600080fd5b863567ffffffffffffffff80821115611b0557600080fd5b611b118a838b0161180c565b90985096506020890135915080821115611b2a57600080fd5b611b368a838b0161180c565b90965094506040890135915080821115611b4f57600080fd5b50611b5c89828a0161180c565b979a9699509497509295939492505050565b60008060008060408587031215611b8457600080fd5b843567ffffffffffffffff80821115611b9c57600080fd5b611ba88883890161180c565b90965094506020870135915080821115611bc157600080fd5b50611bce8782880161180c565b95989497509550505050565b60008060408385031215611bed57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3457835183529284019291840191600101611c18565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cbe57600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf057611cf0611cc8565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5c60a082018561193e565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154857611548611cc8565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6381608885016020870161191a565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb057600080fd5b61197d826117f0565b60008251611cbe81846020870161191a565b600060208284031215611edd57600080fd5b8151801515811461197d57600080fd5b600060208284031215611eff57600080fd5b5051919050565b8082018082111561154857611548611cc8565b600082611f3657634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f63578151835260209283019290910190600101611f44565b50505092915050565b6000808335601e19843603018112611f8357600080fd5b83018035915067ffffffffffffffff821115611f9e57600080fd5b6020019150600581901b360382131561185157600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe757600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea264697066735822122035707b238d9e073c337aa487cf73f97381952577d4eaa9e646e3b4b91b73143c64736f6c63430008140033", + "deployedBytecode": "0x6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d0578063ce757d2914610400578063e4cf5a2c14610416578063eaaba5591461044a578063f1ea66d41461046a57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b057600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b50610189610184366004611858565b61048c565b604051610196919061196a565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611984565b610834565b005b3480156101cd57600080fd5b506101bf6101dc36600461199d565b61089a565b3480156101ed57600080fd5b506102016101fc366004611984565b610b28565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e3660046119ff565b610b49565b34801561026f57600080fd5b506101bf61027e366004611ad4565b610b86565b34801561028f57600080fd5b506102b361029e366004611984565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b6e565b610f43565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611127565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405168756c747261686f6e6b60b81b60208201526029016040516020818303038152906040528051906020012081565b3480156103bc57600080fd5b506101bf6103cb36600461199d565b611187565b3480156103dc57600080fd5b506102b36103eb366004611984565b60046020526000908152604090205460ff1681565b34801561040c57600080fd5b5061020160015481565b34801561042257600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045657600080fd5b50610201610465366004611bda565b61145d565b34801561047657600080fd5b5061047f61154e565b6040516101969190611bfc565b60008781526003602052604090205460609060ff16156104e85760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052e5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104df565b6000805460405161054d9130918c908c908c908c908c90602001611c40565b60405160208183030381529060405280519060200120905060005b8381101561072e576004600086868481811061058657610586611c92565b90506020028101906105989190611ca8565b60209081013582528101919091526040016000205460ff16156105f65760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104df565b61062385858381811061060b5761060b611c92565b905060200281019061061d9190611ca8565b356115a6565b6106665760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104df565b6106938286868481811061067c5761067c611c92565b905060200281019061068e9190611ca8565b6115fc565b6106cf5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104df565b6001600460008787858181106106e7576106e7611c92565b90506020028101906106f99190611ca8565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072681611cde565b915050610568565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610766908b908b90611cf7565b60006040518083038185875af1925050503d80600081146107a3576040519150601f19603f3d011682016040523d82523d6000602084013e6107a8565b606091505b5091509150816107e65760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104df565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081e959493929190611d07565b60405180910390a29a9950505050505050505050565b3330146108535760405162461bcd60e51b81526004016104df90611d68565b600081116108735760405162461bcd60e51b81526004016104df90611d8a565b6002548111156108955760405162461bcd60e51b81526004016104df90611dc1565b600155565b3330146108b95760405162461bcd60e51b81526004016104df90611d68565b816108f45760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b60025482106109455760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104df565b600081116109655760405162461bcd60e51b81526004016104df90611d8a565b600254610973908390611df1565b8111156109925760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b20576000805b600254811015610ac8578585848181106109bd576109bd611c92565b90506020020135600282815481106109d7576109d7611c92565b906000526020600020015403610ab657600280546109f790600190611df1565b81548110610a0757610a07611c92565b906000526020600020015460028281548110610a2557610a25611c92565b6000918252602090912001556002805480610a4257610a42611e04565b6001900381819060005260206000200160009055905560019150858584818110610a6e57610a6e611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aa9911515815260200190565b60405180910390a2610ac8565b80610ac081611cde565b9150506109a1565b5080610b0d5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104df565b5080610b1881611cde565b915050610995565b506001555050565b60028181548110610b3857600080fd5b600091825260209091200154905081565b60008054604051610b669130918890889088908890602001611e1a565b604051602081830303815290604052805190602001209050949350505050565b333014610ba55760405162461bcd60e51b81526004016104df90611d68565b848314610bc45760405162461bcd60e51b81526004016104df90611e75565b848114610be35760405162461bcd60e51b81526004016104df90611e75565b84610c1e5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b85811015610f3a576000878783818110610c3d57610c3d611c92565b9050602002016020810190610c529190611e9e565b6001600160a01b031603610c9c5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b6000838383818110610cb057610cb0611c92565b9050602002016020810190610cc59190611e9e565b6001600160a01b031603610db0576000878783818110610ce757610ce7611c92565b9050602002016020810190610cfc9190611e9e565b6001600160a01b0316868684818110610d1757610d17611c92565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5e576040519150601f19603f3d011682016040523d82523d6000602084013e610d63565b606091505b5050905080610daa5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104df565b50610f28565b600080848484818110610dc557610dc5611c92565b9050602002016020810190610dda9190611e9e565b6001600160a01b0316898985818110610df557610df5611c92565b9050602002016020810190610e0a9190611e9e565b888886818110610e1c57610e1c611c92565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e759190611eb9565b6000604051808303816000865af19150503d8060008114610eb2576040519150601f19603f3d011682016040523d82523d6000602084013e610eb7565b606091505b5091509150818015610ee1575080511580610ee1575080806020019051810190610ee19190611ecb565b610f255760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104df565b50505b80610f3281611cde565b915050610c21565b50505050505050565b333014610f625760405162461bcd60e51b81526004016104df90611d68565b828114610f815760405162461bcd60e51b81526004016104df90611e75565b82610fbc5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b83811015611120576000858583818110610fdb57610fdb611c92565b9050602002016020810190610ff09190611e9e565b6001600160a01b03160361103a5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b600085858381811061104e5761104e611c92565b90506020020160208101906110639190611e9e565b6001600160a01b031684848481811061107e5761107e611c92565b9050602002013560405160006040518083038185875af1925050503d80600081146110c5576040519150601f19603f3d011682016040523d82523d6000602084013e6110ca565b606091505b505090508061110d5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104df565b508061111881611cde565b915050610fbf565b5050505050565b604080516000815260208101918290526002916111449190611eb9565b602060405180830381855afa158015611161573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111849190611eed565b81565b3330146111a65760405162461bcd60e51b81526004016104df90611d68565b816111e15760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b600081116112015760405162461bcd60e51b81526004016104df90611d8a565b60025461120f908390611f06565b81111561122e5760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b205783838281811061124b5761124b611c92565b905060200201356000036112965760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104df565b60005b60025481101561132d578484838181106112b5576112b5611c92565b90506020020135600282815481106112cf576112cf611c92565b90600052602060002001540361131b5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104df565b8061132581611cde565b915050611299565b5060005b818110156113bf5784848381811061134b5761134b611c92565b9050602002013585858381811061136457611364611c92565b90506020020135036113ad5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104df565b806113b781611cde565b915050611331565b5060028484838181106113d4576113d4611c92565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140857611408611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611443911515815260200190565b60405180910390a28061145581611cde565b915050611231565b60008061148a7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b905060006114b87f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b604080518082018252848152602081018390529051632b0aac7f60e11b815291925073__$75f79a42d9bcbdbb69ad79ebd80f556f39$__9163561558fe9161150291600401611f3b565b602060405180830381865af415801561151f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115439190611eed565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159c57602002820191906000526020600020905b815481526020019060010190808311611588575b5050505050905090565b6000805b6002548110156115f35782600282815481106115c8576115c8611c92565b9060005260206000200154036115e15750600192915050565b806115eb81611cde565b9150506115aa565b50600092915050565b60008061160a84600161145d565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845268756c747261686f6e6b60b81b60a08401528351608981850301815260a9840180865281519190930120600080845260c9909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a69190611eb9565b602060405180830381855afa1580156116c3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e69190611eed565b8480519060200120604051602001611717949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e3686606001358760400135848980608001906117799190611f6c565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a59796959493929190611fb6565b602060405180830381865afa1580156117c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e69190611ecb565b9695505050505050565b80356001600160a01b038116811461180757600080fd5b919050565b60008083601f84011261181e57600080fd5b50813567ffffffffffffffff81111561183657600080fd5b6020830191508360208260051b850101111561185157600080fd5b9250929050565b600080600080600080600060a0888a03121561187357600080fd5b87359650611883602089016117f0565b955060408801359450606088013567ffffffffffffffff808211156118a757600080fd5b818a0191508a601f8301126118bb57600080fd5b8135818111156118ca57600080fd5b8b60208285010111156118dc57600080fd5b6020830196508095505060808a01359150808211156118fa57600080fd5b506119078a828b0161180c565b989b979a50959850939692959293505050565b60005b8381101561193557818101518382015260200161191d565b50506000910152565b6000815180845261195681602086016020860161191a565b601f01601f19169290920160200192915050565b60208152600061197d602083018461193e565b9392505050565b60006020828403121561199657600080fd5b5035919050565b6000806000604084860312156119b257600080fd5b833567ffffffffffffffff8111156119c957600080fd5b6119d58682870161180c565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1557600080fd5b84359350611a25602086016117f0565b925060408501359150606085013567ffffffffffffffff80821115611a4957600080fd5b818701915087601f830112611a5d57600080fd5b813581811115611a6f57611a6f6119e9565b604051601f8201601f19908116603f01168101908382118183101715611a9757611a976119e9565b816040528281528a6020848701011115611ab057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aed57600080fd5b863567ffffffffffffffff80821115611b0557600080fd5b611b118a838b0161180c565b90985096506020890135915080821115611b2a57600080fd5b611b368a838b0161180c565b90965094506040890135915080821115611b4f57600080fd5b50611b5c89828a0161180c565b979a9699509497509295939492505050565b60008060008060408587031215611b8457600080fd5b843567ffffffffffffffff80821115611b9c57600080fd5b611ba88883890161180c565b90965094506020870135915080821115611bc157600080fd5b50611bce8782880161180c565b95989497509550505050565b60008060408385031215611bed57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3457835183529284019291840191600101611c18565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cbe57600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf057611cf0611cc8565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5c60a082018561193e565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154857611548611cc8565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6381608885016020870161191a565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb057600080fd5b61197d826117f0565b60008251611cbe81846020870161191a565b600060208284031215611edd57600080fd5b8151801515811461197d57600080fd5b600060208284031215611eff57600080fd5b5051919050565b8082018082111561154857611548611cc8565b600082611f3657634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f63578151835260209283019290910190600101611f44565b50505092915050565b6000808335601e19843603018112611f8357600080fd5b83018035915067ffffffffffffffff821115611f9e57600080fd5b6020019150600581901b360382131561185157600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe757600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea264697066735822122035707b238d9e073c337aa487cf73f97381952577d4eaa9e646e3b4b91b73143c64736f6c63430008140033", "libraries": { "PoseidonT3": "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93" }, diff --git a/packages/hardhat/deployments/horizenTestnet/solcInputs/10833bafee6b78acc8e4896ca53dfe58.json b/packages/hardhat/deployments/horizenTestnet/solcInputs/10833bafee6b78acc8e4896ca53dfe58.json new file mode 100644 index 00000000..79e1a88d --- /dev/null +++ b/packages/hardhat/deployments/horizenTestnet/solcInputs/10833bafee6b78acc8e4896ca53dfe58.json @@ -0,0 +1,39 @@ +{ + "language": "Solidity", + "sources": { + "contracts/MetaMultiSigWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport \"poseidon-solidity/PoseidonT3.sol\";\n\ninterface IVerifyProofAggregation {\n function verifyProofAggregation(\n uint256 _domainId,\n uint256 _aggregationId,\n bytes32 _leaf,\n bytes32[] calldata _merklePath,\n uint256 _leafCount,\n uint256 _index\n ) external view returns (bool);\n}\n\ncontract MetaMultiSigWallet {\n // ============ Constants ============\n bytes32 public constant PROVING_SYSTEM_ID = keccak256(abi.encodePacked(\"ultrahonk\"));\n bytes32 public constant VERSION_HASH = sha256(abi.encodePacked(\"\"));\n uint256 public constant BN254_PRIME = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n\n // ============ Events ============\n event Deposit(address indexed sender, uint256 amount, uint256 balance);\n event TransactionExecuted(uint256 indexed nonce, address to, uint256 value, bytes data, bytes result);\n event Owner(uint256 indexed commitment, bool isAdded);\n\n // ============ Structs ============\n struct ZkProof {\n uint256 commitment;\n uint256 nullifier;\n uint256 aggregationId;\n uint256 domainId;\n bytes32[] zkMerklePath;\n uint256 leafCount;\n uint256 index;\n }\n\n // ============ State ============\n address public immutable zkvContract;\n bytes32 public immutable vkHash;\n uint256 public chainId;\n uint256 public signaturesRequired;\n\n // Signer management\n uint256[] public commitments;\n\n // Nonce tracking (prevent replay)\n mapping(uint256 => bool) public usedNonces;\n\n // Nullifier tracking (prevent double-signing)\n mapping(uint256 => bool) public usedNullifiers;\n\n // ============ Constructor ============\n constructor(\n address _zkvContract,\n bytes32 _vkHash,\n uint256 _chainId,\n uint256[] memory _initialCommitments,\n uint256 _signaturesRequired\n ) {\n require(_zkvContract != address(0), \"Invalid zkv address\");\n require(_signaturesRequired > 0, \"Must be non-zero sigs required\");\n require(_initialCommitments.length > 0, \"Need at least 1 signer\");\n require(_signaturesRequired <= _initialCommitments.length, \"Sigs required too high\");\n\n zkvContract = _zkvContract;\n vkHash = _vkHash;\n chainId = _chainId;\n signaturesRequired = _signaturesRequired;\n\n for (uint256 i = 0; i < _initialCommitments.length; i++) {\n require(_initialCommitments[i] != 0, \"Invalid commitment\");\n commitments.push(_initialCommitments[i]);\n emit Owner(_initialCommitments[i], true);\n }\n }\n\n // ============ Modifiers ============\n modifier onlySelf() {\n require(msg.sender == address(this), \"Not Self\");\n _;\n }\n\n // ============ Main Execute Function ============\n function execute(\n uint256 _nonce,\n address to,\n uint256 value,\n bytes calldata data,\n ZkProof[] calldata proofs\n ) external returns (bytes memory) {\n require(!usedNonces[_nonce], \"Nonce already used\");\n require(proofs.length >= signaturesRequired, \"Not enough proofs\");\n\n bytes32 txHash = keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\n\n for (uint256 i = 0; i < proofs.length; i++) {\n require(!usedNullifiers[proofs[i].nullifier], \"Nullifier already used\");\n require(_isCurrentSigner(proofs[i].commitment), \"Not a current signer\");\n require(_verifyProof(txHash, proofs[i]), \"Invalid proof\");\n usedNullifiers[proofs[i].nullifier] = true;\n }\n\n usedNonces[_nonce] = true;\n\n (bool success, bytes memory result) = to.call{ value: value }(data);\n require(success, \"Tx failed\");\n\n emit TransactionExecuted(_nonce, to, value, data, result);\n return result;\n }\n\n // ============ Signer Management ============\n function addSigners(uint256[] calldata newCommitments, uint256 newSigRequired) public onlySelf {\n require(newCommitments.length > 0, \"Empty array\");\n require(newSigRequired > 0, \"Must be non-zero sigs required\");\n require(newSigRequired <= commitments.length + newCommitments.length, \"Sigs required too high\");\n\n for (uint256 i = 0; i < newCommitments.length; i++) {\n require(newCommitments[i] != 0, \"Invalid commitment\");\n \n // Check duplicate with existing signers\n for (uint256 j = 0; j < commitments.length; j++) {\n require(commitments[j] != newCommitments[i], \"Commitment exists\");\n }\n \n // Check duplicate within input array\n for (uint256 k = 0; k < i; k++) {\n require(newCommitments[k] != newCommitments[i], \"Duplicate in input\");\n }\n\n commitments.push(newCommitments[i]);\n emit Owner(newCommitments[i], true);\n }\n\n signaturesRequired = newSigRequired;\n }\n\n function removeSigners(uint256[] calldata commitmentsToRemove, uint256 newSigRequired) public onlySelf {\n require(commitmentsToRemove.length > 0, \"Empty array\");\n require(commitments.length > commitmentsToRemove.length, \"Cannot remove all signers\");\n require(newSigRequired > 0, \"Must be non-zero sigs required\");\n require(newSigRequired <= commitments.length - commitmentsToRemove.length, \"Sigs required too high\");\n\n for (uint256 i = 0; i < commitmentsToRemove.length; i++) {\n bool found = false;\n for (uint256 j = 0; j < commitments.length; j++) {\n if (commitments[j] == commitmentsToRemove[i]) {\n commitments[j] = commitments[commitments.length - 1];\n commitments.pop();\n found = true;\n emit Owner(commitmentsToRemove[i], false);\n break;\n }\n }\n require(found, \"Commitment not found\");\n }\n\n signaturesRequired = newSigRequired;\n }\n\n function updateSignaturesRequired(uint256 newSigRequired) public onlySelf {\n require(newSigRequired > 0, \"Must be non-zero sigs required\");\n require(newSigRequired <= commitments.length, \"Sigs required too high\");\n signaturesRequired = newSigRequired;\n }\n\n /**\n * @notice Execute multiple transfers in one transaction\n * @param recipients Array of recipient addresses\n * @param amounts Array of amounts to send\n */\n function batchTransfer(address[] calldata recipients, uint256[] calldata amounts) public onlySelf {\n require(recipients.length == amounts.length, \"Length mismatch\");\n require(recipients.length > 0, \"Empty batch\");\n\n for (uint256 i = 0; i < recipients.length; i++) {\n require(recipients[i] != address(0), \"Invalid recipient\");\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\"\");\n require(success, \"Transfer failed\");\n }\n }\n\n /**\n * @notice Execute multiple transfers with mixed token types\n * @param recipients Array of recipient addresses\n * @param amounts Array of amounts to send\n * @param tokenAddresses Array of token addresses (address(0) = native ETH)\n */\n function batchTransferMulti(\n address[] calldata recipients,\n uint256[] calldata amounts,\n address[] calldata tokenAddresses\n ) public onlySelf {\n require(recipients.length == amounts.length, \"Length mismatch\");\n require(recipients.length == tokenAddresses.length, \"Length mismatch\");\n require(recipients.length > 0, \"Empty batch\");\n\n for (uint256 i = 0; i < recipients.length; i++) {\n require(recipients[i] != address(0), \"Invalid recipient\");\n\n if (tokenAddresses[i] == address(0)) {\n // Native ETH transfer\n (bool success, ) = recipients[i].call{ value: amounts[i] }(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n // ERC20 transfer\n (bool success, bytes memory data) = tokenAddresses[i].call(\n abi.encodeWithSignature(\"transfer(address,uint256)\", recipients[i], amounts[i])\n );\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"ERC20 transfer failed\");\n }\n }\n }\n\n // ============ View Functions ============\n function getTransactionHash(\n uint256 _nonce,\n address to,\n uint256 value,\n bytes memory data\n ) public view returns (bytes32) {\n return keccak256(abi.encodePacked(address(this), chainId, _nonce, to, value, data));\n }\n\n function getCommitments() external view returns (uint256[] memory) {\n return commitments;\n }\n\n function getSignersCount() external view returns (uint256) {\n return commitments.length;\n }\n\n // ============ Internal Functions ============\n function _verifyProof(bytes32 txHash, ZkProof calldata proof) internal view returns (bool) {\n uint256 txHashCommitment = poseidonHash2(uint256(txHash), 1);\n\n // Public inputs order: tx_hash_commitment, commitment, nullifier\n bytes memory encodedInputs = abi.encodePacked(txHashCommitment, proof.commitment, proof.nullifier);\n\n bytes32 leaf = keccak256(abi.encodePacked(PROVING_SYSTEM_ID, vkHash, VERSION_HASH, keccak256(encodedInputs)));\n\n return\n IVerifyProofAggregation(zkvContract).verifyProofAggregation(\n proof.domainId,\n proof.aggregationId,\n leaf,\n proof.zkMerklePath,\n proof.leafCount,\n proof.index\n );\n }\n\n function _isCurrentSigner(uint256 commitment) internal view returns (bool) {\n for (uint256 i = 0; i < commitments.length; i++) {\n if (commitments[i] == commitment) {\n return true;\n }\n }\n return false;\n }\n\n // ============ Receive ETH ============\n receive() external payable {\n emit Deposit(msg.sender, msg.value, address(this).balance);\n }\n\n function poseidonHash2(uint256 a, uint256 b) public pure returns (uint256) {\n uint256 safeA = a % BN254_PRIME;\n uint256 safeB = b % BN254_PRIME;\n return PoseidonT3.hash([safeA, safeB]);\n }\n}" + }, + "poseidon-solidity/PoseidonT3.sol": { + "content": "/// SPDX-License-Identifier: MIT\npragma solidity >=0.7.0;\n\nlibrary PoseidonT3 {\n uint constant M00 = 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b;\n uint constant M01 = 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771;\n uint constant M02 = 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7;\n uint constant M10 = 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0;\n uint constant M11 = 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23;\n uint constant M12 = 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911;\n\n // See here for a simplified implementation: https://github.com/vimwitch/poseidon-solidity/blob/e57becdabb65d99fdc586fe1e1e09e7108202d53/contracts/Poseidon.sol#L40\n // Inspired by: https://github.com/iden3/circomlibjs/blob/v0.0.8/src/poseidon_slow.js\n function hash(uint[2] memory) public pure returns (uint) {\n assembly {\n let F := 21888242871839275222246405745257275088548364400416034343698204186575808495617\n let M20 := 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d\n let M21 := 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa\n let M22 := 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0\n\n // load the inputs from memory\n let state1 := add(mod(mload(0x80), F), 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864)\n let state2 := add(mod(mload(0xa0), F), 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5)\n let scratch0 := mulmod(state1, state1, F)\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\n scratch0 := mulmod(state2, state2, F)\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\n scratch0 := add(\n 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0,\n add(add(15452833169820924772166449970675545095234312153403844297388521437673434406763, mulmod(state1, M10, F)), mulmod(state2, M20, F))\n )\n let scratch1 := add(\n 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2,\n add(add(18674271267752038776579386132900109523609358935013267566297499497165104279117, mulmod(state1, M11, F)), mulmod(state2, M21, F))\n )\n let scratch2 := add(\n 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa,\n add(add(14817777843080276494683266178512808687156649753153012854386334860566696099579, mulmod(state1, M12, F)), mulmod(state2, M22, F))\n )\n let state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := mulmod(scratch1, scratch1, F)\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\n state0 := mulmod(scratch2, scratch2, F)\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\n state0 := add(0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := mulmod(state1, state1, F)\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\n scratch0 := mulmod(state2, state2, F)\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\n scratch0 := add(0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := mulmod(scratch1, scratch1, F)\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\n state0 := mulmod(scratch2, scratch2, F)\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\n state0 := add(0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := add(0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := add(0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := mulmod(scratch1, scratch1, F)\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\n state0 := mulmod(scratch2, scratch2, F)\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\n state0 := add(0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := mulmod(state1, state1, F)\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\n scratch0 := mulmod(state2, state2, F)\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\n scratch0 := add(0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)))\n scratch1 := add(0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F)))\n scratch2 := add(0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F)))\n state0 := mulmod(scratch0, scratch0, F)\n scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F)\n state0 := mulmod(scratch1, scratch1, F)\n scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F)\n state0 := mulmod(scratch2, scratch2, F)\n scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F)\n state0 := add(0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F)))\n state1 := add(0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F)))\n state2 := add(0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F)))\n scratch0 := mulmod(state0, state0, F)\n state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F)\n scratch0 := mulmod(state1, state1, F)\n state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F)\n scratch0 := mulmod(state2, state2, F)\n state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F)\n\n mstore(0x0, mod(add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)), F))\n\n return(0, 0x20)\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 6b9a414a..fc5d8122 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; const deployedContracts = { 2651420: { MetaMultiSigWallet: { - address: "0x1EaCA128069b2bb1cd476ef66E2701F98cAB148E", + address: "0xE146bA86fef4056566D7EE9dBB9fFaCf8A994AC2", abi: [ { inputs: [ @@ -525,7 +525,7 @@ const deployedContracts = { }, ], inheritedFunctions: {}, - deployedOnBlock: 6615581, + deployedOnBlock: 13507810, }, }, 11155111: { diff --git a/packages/nextjs/hooks/app/transaction/useBatchTransaction.ts b/packages/nextjs/hooks/app/transaction/useBatchTransaction.ts index c359911e..82baa4aa 100644 --- a/packages/nextjs/hooks/app/transaction/useBatchTransaction.ts +++ b/packages/nextjs/hooks/app/transaction/useBatchTransaction.ts @@ -93,7 +93,7 @@ export const useBatchTransaction = (options?: UseBatchTransactionOptions) => { nullifier: nullifier.toString(), batchItemIds: selectedIds, userAddress: walletClient.account.address, - vk: vk ? Buffer.from(vk).toString("base64") : undefined, + vk, }); if (result) { diff --git a/packages/nextjs/hooks/app/transaction/useSignerTransaction.ts b/packages/nextjs/hooks/app/transaction/useSignerTransaction.ts index 7da7dabb..30cfedb8 100644 --- a/packages/nextjs/hooks/app/transaction/useSignerTransaction.ts +++ b/packages/nextjs/hooks/app/transaction/useSignerTransaction.ts @@ -72,7 +72,7 @@ export const useSignerTransaction = (options?: UseSignerTransactionOptions) => { publicInputs, nullifier, userAddress: walletClient.account.address, - vk: vk ? Buffer.from(vk).toString("base64") : undefined, + vk, ...txPayload, }); diff --git a/packages/nextjs/hooks/app/transaction/useTransactionVote.ts b/packages/nextjs/hooks/app/transaction/useTransactionVote.ts index 529cc406..ccc4a1e4 100644 --- a/packages/nextjs/hooks/app/transaction/useTransactionVote.ts +++ b/packages/nextjs/hooks/app/transaction/useTransactionVote.ts @@ -172,7 +172,7 @@ export const useTransactionVote = (options?: UseTransactionVoteOptions) => { publicInputs: proofData.publicInputs, nullifier: proofData.nullifier, userAddress: walletClient.account.address, - vk: proofData.vk ? Buffer.from(proofData.vk).toString("base64") : undefined, + vk: proofData.vk, }, }); diff --git a/packages/nextjs/hooks/app/transaction/useTransferTransaction.ts b/packages/nextjs/hooks/app/transaction/useTransferTransaction.ts index c7f900b5..261afb6a 100644 --- a/packages/nextjs/hooks/app/transaction/useTransferTransaction.ts +++ b/packages/nextjs/hooks/app/transaction/useTransferTransaction.ts @@ -94,7 +94,7 @@ export const useTransferTransaction = (options?: UseTransferTransactionOptions) publicInputs, nullifier: nullifier.toString(), userAddress: walletClient.account.address, - vk: vk ? Buffer.from(vk).toString("base64") : undefined, + vk, }); if (result) { diff --git a/packages/nextjs/hooks/app/useAuth.ts b/packages/nextjs/hooks/app/useAuth.ts index 91b936b6..2bbc1de3 100644 --- a/packages/nextjs/hooks/app/useAuth.ts +++ b/packages/nextjs/hooks/app/useAuth.ts @@ -40,7 +40,7 @@ export const useAuth = () => { commitment: proofResult.commitment, proof: proofResult.proof, publicInputs: proofResult.publicInputs, - vk: Buffer.from(proofResult.vk).toString("base64"), + vk: proofResult.vk, walletAddress: proofResult.walletAddress, // For analytics only }); diff --git a/packages/nextjs/hooks/app/useAuthProof.ts b/packages/nextjs/hooks/app/useAuthProof.ts index 70572625..679dbd3b 100644 --- a/packages/nextjs/hooks/app/useAuthProof.ts +++ b/packages/nextjs/hooks/app/useAuthProof.ts @@ -8,7 +8,7 @@ interface AuthProofResult { commitment: string; proof: number[]; publicInputs: string[]; - vk?: any; + vk?: string; walletAddress: string; // For analytics only } @@ -46,17 +46,18 @@ export const useAuthProof = () => { }; // 5. Generate proof - const [{ Noir }, { UltraPlonkBackend }] = await Promise.all([ + const [{ Noir }, { UltraHonkBackend }] = await Promise.all([ import("@noir-lang/noir_js"), import("@aztec/bb.js"), ]); - const backend = new UltraPlonkBackend(bytecode); + const backend = new UltraHonkBackend(bytecode); const noir = new Noir({ bytecode, abi } as any); const { witness } = await noir.execute(circuitInputs); - const { proof, publicInputs } = await backend.generateProof(witness); - const vk = await backend.getVerificationKey(); + const { proof, publicInputs } = await backend.generateProof(witness, { keccak: true }); + const rawVk = await backend.getVerificationKey({ keccak: true }); + const vk = "0x" + Buffer.from(rawVk).toString("hex"); // 6. Format output const proofArray = Array.from(proof); diff --git a/packages/nextjs/hooks/app/useGenerateProof.ts b/packages/nextjs/hooks/app/useGenerateProof.ts index 8b003dc5..94ff0ec9 100644 --- a/packages/nextjs/hooks/app/useGenerateProof.ts +++ b/packages/nextjs/hooks/app/useGenerateProof.ts @@ -15,7 +15,7 @@ export interface GenerateProofResult { publicInputs: string[]; nullifier: string; commitment: string; - vk?: any; + vk?: string; } export interface UseGenerateProofOptions { @@ -94,10 +94,7 @@ export function useGenerateProof(options?: UseGenerateProofOptions) { // 5. Dynamic import Noir libraries setLoadingState("Loading ZK libraries..."); - const [{ Noir }, { UltraPlonkBackend }] = await Promise.all([ - import("@noir-lang/noir_js"), - import("@aztec/bb.js"), - ]); + const { Noir } = await import("@noir-lang/noir_js"); // 6. Execute Noir circuit const input = { @@ -114,11 +111,25 @@ export function useGenerateProof(options?: UseGenerateProofOptions) { const noir = new Noir({ bytecode, abi } as any); const execResult = await noir.execute(input); - // 7. Generate proof + // 7. Generate proof — use UltraHonk for contractVersion >= 2 setLoadingState("Securing your transaction..."); - const plonk = new UltraPlonkBackend(bytecode, { threads: 2 }); - const { proof, publicInputs } = await plonk.generateProof(execResult.witness); - // const vk = await plonk.getVerificationKey(); + let proof: Uint8Array; + let publicInputs: string[]; + let vk: string | undefined; + + if (currentAccount?.contractVersion && currentAccount.contractVersion >= 2) { + const { UltraHonkBackend } = await import("@aztec/bb.js"); + const backend = new UltraHonkBackend(bytecode, { threads: 2 }); + ({ proof, publicInputs } = await backend.generateProof(execResult.witness, { keccak: true })); + const rawVk = await backend.getVerificationKey({ keccak: true }); + vk = "0x" + Buffer.from(rawVk).toString("hex"); + } else { + const { UltraPlonkBackend } = await import("@aztec/bb.js"); + const backend = new UltraPlonkBackend(bytecode, { threads: 2 }); + ({ proof, publicInputs } = await backend.generateProof(execResult.witness)); + const rawVk = await backend.getVerificationKey(); + vk = Buffer.from(rawVk).toString("base64"); + } setLoadingState(""); @@ -127,7 +138,7 @@ export function useGenerateProof(options?: UseGenerateProofOptions) { publicInputs, nullifier: nullifier.toString(), commitment, - // vk + vk, }; }, [ diff --git a/packages/shared/src/contracts/MetaMultiSigWallet.ts b/packages/shared/src/contracts/MetaMultiSigWallet.ts index 1a3e8d9b..b08b68b9 100644 --- a/packages/shared/src/contracts/MetaMultiSigWallet.ts +++ b/packages/shared/src/contracts/MetaMultiSigWallet.ts @@ -518,4 +518,4 @@ export const METAMULTISIG_ABI = [ // ============ Bytecode ============ export const METAMULTISIG_BYTECODE = - "0x60c06040523480156200001157600080fd5b50604051620024a0380380620024a08339810160408190526200003491620002db565b6001600160a01b038516620000905760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207a6b7620616464726573730000000000000000000000000060448201526064015b60405180910390fd5b60008111620000e25760405162461bcd60e51b815260206004820152601e60248201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604482015260640162000087565b6000825111620001355760405162461bcd60e51b815260206004820152601660248201527f4e656564206174206c656173742031207369676e657200000000000000000000604482015260640162000087565b8151811115620001885760405162461bcd60e51b815260206004820152601660248201527f5369677320726571756972656420746f6f206869676800000000000000000000604482015260640162000087565b6001600160a01b03851660805260a0849052600083815560018290555b8251811015620002b957828181518110620001c457620001c4620003e6565b6020026020010151600003620002125760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b604482015260640162000087565b6002838281518110620002295762000229620003e6565b6020908102919091018101518254600181018455600093845291909220015582518390829081106200025f576200025f620003e6565b60200260200101517f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d60016040516200029c911515815260200190565b60405180910390a280620002b081620003fc565b915050620001a5565b50505050505062000424565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620002f457600080fd5b85516001600160a01b03811681146200030c57600080fd5b602087810151604089015160608a01519398509096509450906001600160401b03808211156200033b57600080fd5b818901915089601f8301126200035057600080fd5b815181811115620003655762000365620002c5565b8060051b604051601f19603f830116810181811085821117156200038d576200038d620002c5565b60405291825284820192508381018501918c831115620003ac57600080fd5b938501935b82851015620003cc57845184529385019392850192620003b1565b809750505050505050608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6000600182016200041d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a0516120486200045860003960008181610221015261167b0152600081816102d5015261173301526120486000f3fe6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d1578063ce757d2914610401578063e4cf5a2c14610417578063eaaba5591461044b578063f1ea66d41461046b57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b157600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b5061018961018436600461185a565b61048d565b604051610196919061196c565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611986565b610835565b005b3480156101cd57600080fd5b506101bf6101dc36600461199f565b61089b565b3480156101ed57600080fd5b506102016101fc366004611986565b610b29565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e366004611a01565b610b4a565b34801561026f57600080fd5b506101bf61027e366004611ad6565b610b87565b34801561028f57600080fd5b506102b361029e366004611986565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b70565b610f44565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611128565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405169756c747261706c6f6e6b60b01b6020820152602a016040516020818303038152906040528051906020012081565b3480156103bd57600080fd5b506101bf6103cc36600461199f565b611188565b3480156103dd57600080fd5b506102b36103ec366004611986565b60046020526000908152604090205460ff1681565b34801561040d57600080fd5b5061020160015481565b34801561042357600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045757600080fd5b50610201610466366004611bdc565b61145e565b34801561047757600080fd5b5061048061154f565b6040516101969190611bfe565b60008781526003602052604090205460609060ff16156104e95760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052f5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104e0565b6000805460405161054e9130918c908c908c908c908c90602001611c42565b60405160208183030381529060405280519060200120905060005b8381101561072f576004600086868481811061058757610587611c94565b90506020028101906105999190611caa565b60209081013582528101919091526040016000205460ff16156105f75760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104e0565b61062485858381811061060c5761060c611c94565b905060200281019061061e9190611caa565b356115a7565b6106675760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104e0565b6106948286868481811061067d5761067d611c94565b905060200281019061068f9190611caa565b6115fd565b6106d05760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104e0565b6001600460008787858181106106e8576106e8611c94565b90506020028101906106fa9190611caa565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072781611ce0565b915050610569565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610767908b908b90611cf9565b60006040518083038185875af1925050503d80600081146107a4576040519150601f19603f3d011682016040523d82523d6000602084013e6107a9565b606091505b5091509150816107e75760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104e0565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081f959493929190611d09565b60405180910390a29a9950505050505050505050565b3330146108545760405162461bcd60e51b81526004016104e090611d6a565b600081116108745760405162461bcd60e51b81526004016104e090611d8c565b6002548111156108965760405162461bcd60e51b81526004016104e090611dc3565b600155565b3330146108ba5760405162461bcd60e51b81526004016104e090611d6a565b816108f55760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b60025482106109465760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104e0565b600081116109665760405162461bcd60e51b81526004016104e090611d8c565b600254610974908390611df3565b8111156109935760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b21576000805b600254811015610ac9578585848181106109be576109be611c94565b90506020020135600282815481106109d8576109d8611c94565b906000526020600020015403610ab757600280546109f890600190611df3565b81548110610a0857610a08611c94565b906000526020600020015460028281548110610a2657610a26611c94565b6000918252602090912001556002805480610a4357610a43611e06565b6001900381819060005260206000200160009055905560019150858584818110610a6f57610a6f611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aaa911515815260200190565b60405180910390a2610ac9565b80610ac181611ce0565b9150506109a2565b5080610b0e5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104e0565b5080610b1981611ce0565b915050610996565b506001555050565b60028181548110610b3957600080fd5b600091825260209091200154905081565b60008054604051610b679130918890889088908890602001611e1c565b604051602081830303815290604052805190602001209050949350505050565b333014610ba65760405162461bcd60e51b81526004016104e090611d6a565b848314610bc55760405162461bcd60e51b81526004016104e090611e77565b848114610be45760405162461bcd60e51b81526004016104e090611e77565b84610c1f5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b85811015610f3b576000878783818110610c3e57610c3e611c94565b9050602002016020810190610c539190611ea0565b6001600160a01b031603610c9d5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b6000838383818110610cb157610cb1611c94565b9050602002016020810190610cc69190611ea0565b6001600160a01b031603610db1576000878783818110610ce857610ce8611c94565b9050602002016020810190610cfd9190611ea0565b6001600160a01b0316868684818110610d1857610d18611c94565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5f576040519150601f19603f3d011682016040523d82523d6000602084013e610d64565b606091505b5050905080610dab5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104e0565b50610f29565b600080848484818110610dc657610dc6611c94565b9050602002016020810190610ddb9190611ea0565b6001600160a01b0316898985818110610df657610df6611c94565b9050602002016020810190610e0b9190611ea0565b888886818110610e1d57610e1d611c94565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e769190611ebb565b6000604051808303816000865af19150503d8060008114610eb3576040519150601f19603f3d011682016040523d82523d6000602084013e610eb8565b606091505b5091509150818015610ee2575080511580610ee2575080806020019051810190610ee29190611ecd565b610f265760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104e0565b50505b80610f3381611ce0565b915050610c22565b50505050505050565b333014610f635760405162461bcd60e51b81526004016104e090611d6a565b828114610f825760405162461bcd60e51b81526004016104e090611e77565b82610fbd5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104e0565b60005b83811015611121576000858583818110610fdc57610fdc611c94565b9050602002016020810190610ff19190611ea0565b6001600160a01b03160361103b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104e0565b600085858381811061104f5761104f611c94565b90506020020160208101906110649190611ea0565b6001600160a01b031684848481811061107f5761107f611c94565b9050602002013560405160006040518083038185875af1925050503d80600081146110c6576040519150601f19603f3d011682016040523d82523d6000602084013e6110cb565b606091505b505090508061110e5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104e0565b508061111981611ce0565b915050610fc0565b5050505050565b604080516000815260208101918290526002916111459190611ebb565b602060405180830381855afa158015611162573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111859190611eef565b81565b3330146111a75760405162461bcd60e51b81526004016104e090611d6a565b816111e25760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104e0565b600081116112025760405162461bcd60e51b81526004016104e090611d8c565b600254611210908390611f08565b81111561122f5760405162461bcd60e51b81526004016104e090611dc3565b60005b82811015610b215783838281811061124c5761124c611c94565b905060200201356000036112975760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104e0565b60005b60025481101561132e578484838181106112b6576112b6611c94565b90506020020135600282815481106112d0576112d0611c94565b90600052602060002001540361131c5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104e0565b8061132681611ce0565b91505061129a565b5060005b818110156113c05784848381811061134c5761134c611c94565b9050602002013585858381811061136557611365611c94565b90506020020135036113ae5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104e0565b806113b881611ce0565b915050611332565b5060028484838181106113d5576113d5611c94565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140957611409611c94565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611444911515815260200190565b60405180910390a28061145681611ce0565b915050611232565b60008061148b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b905060006114b97f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f1b565b604080518082018252848152602081018390529051632b0aac7f60e11b8152919250733333333C0A88F9BE4fd23ed0536F9B6c427e3B939163561558fe9161150391600401611f3d565b602060405180830381865af4158015611520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115449190611eef565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159d57602002820191906000526020600020905b815481526020019060010190808311611589575b5050505050905090565b6000805b6002548110156115f45782600282815481106115c9576115c9611c94565b9060005260206000200154036115e25750600192915050565b806115ec81611ce0565b9150506115ab565b50600092915050565b60008061160b84600161145e565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845269756c747261706c6f6e6b60b01b60a08401528351608a81850301815260aa840180865281519190930120600080845260ca909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a89190611ebb565b602060405180830381855afa1580156116c5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e89190611eef565b8480519060200120604051602001611719949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e36866060013587604001358489806080019061177b9190611f6e565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a79796959493929190611fb8565b602060405180830381865afa1580156117c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e89190611ecd565b9695505050505050565b80356001600160a01b038116811461180957600080fd5b919050565b60008083601f84011261182057600080fd5b50813567ffffffffffffffff81111561183857600080fd5b6020830191508360208260051b850101111561185357600080fd5b9250929050565b600080600080600080600060a0888a03121561187557600080fd5b87359650611885602089016117f2565b955060408801359450606088013567ffffffffffffffff808211156118a957600080fd5b818a0191508a601f8301126118bd57600080fd5b8135818111156118cc57600080fd5b8b60208285010111156118de57600080fd5b6020830196508095505060808a01359150808211156118fc57600080fd5b506119098a828b0161180e565b989b979a50959850939692959293505050565b60005b8381101561193757818101518382015260200161191f565b50506000910152565b6000815180845261195881602086016020860161191c565b601f01601f19169290920160200192915050565b60208152600061197f6020830184611940565b9392505050565b60006020828403121561199857600080fd5b5035919050565b6000806000604084860312156119b457600080fd5b833567ffffffffffffffff8111156119cb57600080fd5b6119d78682870161180e565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1757600080fd5b84359350611a27602086016117f2565b925060408501359150606085013567ffffffffffffffff80821115611a4b57600080fd5b818701915087601f830112611a5f57600080fd5b813581811115611a7157611a716119eb565b604051601f8201601f19908116603f01168101908382118183101715611a9957611a996119eb565b816040528281528a6020848701011115611ab257600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aef57600080fd5b863567ffffffffffffffff80821115611b0757600080fd5b611b138a838b0161180e565b90985096506020890135915080821115611b2c57600080fd5b611b388a838b0161180e565b90965094506040890135915080821115611b5157600080fd5b50611b5e89828a0161180e565b979a9699509497509295939492505050565b60008060008060408587031215611b8657600080fd5b843567ffffffffffffffff80821115611b9e57600080fd5b611baa8883890161180e565b90965094506020870135915080821115611bc357600080fd5b50611bd08782880161180e565b95989497509550505050565b60008060408385031215611bef57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3657835183529284019291840191600101611c1a565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cc057600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf257611cf2611cca565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5e60a0820185611940565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154957611549611cca565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6581608885016020870161191c565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb257600080fd5b61197f826117f2565b60008251611cc081846020870161191c565b600060208284031215611edf57600080fd5b8151801515811461197f57600080fd5b600060208284031215611f0157600080fd5b5051919050565b8082018082111561154957611549611cca565b600082611f3857634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f65578151835260209283019290910190600101611f46565b50505092915050565b6000808335601e19843603018112611f8557600080fd5b83018035915067ffffffffffffffff821115611fa057600080fd5b6020019150600581901b360382131561185357600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe957600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea2646970667358221220925328ba1cb1d89f7ed11053888b9080bbb4027159fb1003d3575f3e6578fd1464736f6c63430008140033"; + "0x60c06040523480156200001157600080fd5b506040516200249e3803806200249e8339810160408190526200003491620002db565b6001600160a01b038516620000905760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207a6b7620616464726573730000000000000000000000000060448201526064015b60405180910390fd5b60008111620000e25760405162461bcd60e51b815260206004820152601e60248201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604482015260640162000087565b6000825111620001355760405162461bcd60e51b815260206004820152601660248201527f4e656564206174206c656173742031207369676e657200000000000000000000604482015260640162000087565b8151811115620001885760405162461bcd60e51b815260206004820152601660248201527f5369677320726571756972656420746f6f206869676800000000000000000000604482015260640162000087565b6001600160a01b03851660805260a0849052600083815560018290555b8251811015620002b957828181518110620001c457620001c4620003e6565b6020026020010151600003620002125760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b604482015260640162000087565b6002838281518110620002295762000229620003e6565b6020908102919091018101518254600181018455600093845291909220015582518390829081106200025f576200025f620003e6565b60200260200101517f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d60016040516200029c911515815260200190565b60405180910390a280620002b081620003fc565b915050620001a5565b50505050505062000424565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620002f457600080fd5b85516001600160a01b03811681146200030c57600080fd5b602087810151604089015160608a01519398509096509450906001600160401b03808211156200033b57600080fd5b818901915089601f8301126200035057600080fd5b815181811115620003655762000365620002c5565b8060051b604051601f19603f830116810181811085821117156200038d576200038d620002c5565b60405291825284820192508381018501918c831115620003ac57600080fd5b938501935b82851015620003cc57845184529385019392850192620003b1565b809750505050505050608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6000600182016200041d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051612046620004586000396000818161022101526116790152600081816102d5015261173101526120466000f3fe6080604052600436106101235760003560e01c80639a8a0592116100a0578063aad2406111610064578063aad24061146103d0578063ce757d2914610400578063e4cf5a2c14610416578063eaaba5591461044a578063f1ea66d41461046a57600080fd5b80639a8a05921461032f5780639e4e731814610345578063a0c1deb41461035a578063a8898a201461036f578063a8d2c852146103b057600080fd5b8063545a4a3c116100e7578063545a4a3c1461024357806364451212146102635780636717e41c146102835780637ee68373146102c357806388d695b21461030f57600080fd5b80631b108c07146101695780633034a7421461019f5780634791ca34146101c157806349ce8997146101e15780634fe840f51461020f57600080fd5b36610164576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561017557600080fd5b50610189610184366004611858565b61048c565b604051610196919061196a565b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba366004611984565b610834565b005b3480156101cd57600080fd5b506101bf6101dc36600461199d565b61089a565b3480156101ed57600080fd5b506102016101fc366004611984565b610b28565b604051908152602001610196565b34801561021b57600080fd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b34801561024f57600080fd5b5061020161025e3660046119ff565b610b49565b34801561026f57600080fd5b506101bf61027e366004611ad4565b610b86565b34801561028f57600080fd5b506102b361029e366004611984565b60036020526000908152604090205460ff1681565b6040519015158152602001610196565b3480156102cf57600080fd5b506102f77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610196565b34801561031b57600080fd5b506101bf61032a366004611b6e565b610f43565b34801561033b57600080fd5b5061020160005481565b34801561035157600080fd5b50610201611127565b34801561036657600080fd5b50600254610201565b34801561037b57600080fd5b5061020160405168756c747261686f6e6b60b81b60208201526029016040516020818303038152906040528051906020012081565b3480156103bc57600080fd5b506101bf6103cb36600461199d565b611187565b3480156103dc57600080fd5b506102b36103eb366004611984565b60046020526000908152604090205460ff1681565b34801561040c57600080fd5b5061020160015481565b34801561042257600080fd5b506102017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181565b34801561045657600080fd5b50610201610465366004611bda565b61145d565b34801561047657600080fd5b5061047f61154e565b6040516101969190611bfc565b60008781526003602052604090205460609060ff16156104e85760405162461bcd60e51b8152602060048201526012602482015271139bdb98d948185b1c9958591e481d5cd95960721b60448201526064015b60405180910390fd5b60015482101561052e5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f7567682070726f6f667360781b60448201526064016104df565b6000805460405161054d9130918c908c908c908c908c90602001611c40565b60405160208183030381529060405280519060200120905060005b8381101561072e576004600086868481811061058657610586611c92565b90506020028101906105989190611ca8565b60209081013582528101919091526040016000205460ff16156105f65760405162461bcd60e51b8152602060048201526016602482015275139d5b1b1a599a595c88185b1c9958591e481d5cd95960521b60448201526064016104df565b61062385858381811061060b5761060b611c92565b905060200281019061061d9190611ca8565b356115a6565b6106665760405162461bcd60e51b81526020600482015260146024820152732737ba10309031bab93932b73a1039b4b3b732b960611b60448201526064016104df565b6106938286868481811061067c5761067c611c92565b905060200281019061068e9190611ca8565b6115fc565b6106cf5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016104df565b6001600460008787858181106106e7576106e7611c92565b90506020028101906106f99190611ca8565b6020908101358252810191909152604001600020805460ff19169115159190911790558061072681611cde565b915050610568565b50600089815260036020526040808220805460ff191660011790555181906001600160a01b038b16908a90610766908b908b90611cf7565b60006040518083038185875af1925050503d80600081146107a3576040519150601f19603f3d011682016040523d82523d6000602084013e6107a8565b606091505b5091509150816107e65760405162461bcd60e51b8152602060048201526009602482015268151e0819985a5b195960ba1b60448201526064016104df565b8a7f1654479f61781d185c419742a20e599a227ae1840317c8a74ceda5eb6166b8268b8b8b8b8660405161081e959493929190611d07565b60405180910390a29a9950505050505050505050565b3330146108535760405162461bcd60e51b81526004016104df90611d68565b600081116108735760405162461bcd60e51b81526004016104df90611d8a565b6002548111156108955760405162461bcd60e51b81526004016104df90611dc1565b600155565b3330146108b95760405162461bcd60e51b81526004016104df90611d68565b816108f45760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b60025482106109455760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072656d6f766520616c6c207369676e6572730000000000000060448201526064016104df565b600081116109655760405162461bcd60e51b81526004016104df90611d8a565b600254610973908390611df1565b8111156109925760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b20576000805b600254811015610ac8578585848181106109bd576109bd611c92565b90506020020135600282815481106109d7576109d7611c92565b906000526020600020015403610ab657600280546109f790600190611df1565b81548110610a0757610a07611c92565b906000526020600020015460028281548110610a2557610a25611c92565b6000918252602090912001556002805480610a4257610a42611e04565b6001900381819060005260206000200160009055905560019150858584818110610a6e57610a6e611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6000604051610aa9911515815260200190565b60405180910390a2610ac8565b80610ac081611cde565b9150506109a1565b5080610b0d5760405162461bcd60e51b815260206004820152601460248201527310dbdb5b5a5d1b595b9d081b9bdd08199bdd5b9960621b60448201526064016104df565b5080610b1881611cde565b915050610995565b506001555050565b60028181548110610b3857600080fd5b600091825260209091200154905081565b60008054604051610b669130918890889088908890602001611e1a565b604051602081830303815290604052805190602001209050949350505050565b333014610ba55760405162461bcd60e51b81526004016104df90611d68565b848314610bc45760405162461bcd60e51b81526004016104df90611e75565b848114610be35760405162461bcd60e51b81526004016104df90611e75565b84610c1e5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b85811015610f3a576000878783818110610c3d57610c3d611c92565b9050602002016020810190610c529190611e9e565b6001600160a01b031603610c9c5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b6000838383818110610cb057610cb0611c92565b9050602002016020810190610cc59190611e9e565b6001600160a01b031603610db0576000878783818110610ce757610ce7611c92565b9050602002016020810190610cfc9190611e9e565b6001600160a01b0316868684818110610d1757610d17611c92565b9050602002013560405160006040518083038185875af1925050503d8060008114610d5e576040519150601f19603f3d011682016040523d82523d6000602084013e610d63565b606091505b5050905080610daa5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016104df565b50610f28565b600080848484818110610dc557610dc5611c92565b9050602002016020810190610dda9190611e9e565b6001600160a01b0316898985818110610df557610df5611c92565b9050602002016020810190610e0a9190611e9e565b888886818110610e1c57610e1c611c92565b6040516001600160a01b039094166024850152602002919091013560448301525060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251610e759190611eb9565b6000604051808303816000865af19150503d8060008114610eb2576040519150601f19603f3d011682016040523d82523d6000602084013e610eb7565b606091505b5091509150818015610ee1575080511580610ee1575080806020019051810190610ee19190611ecb565b610f255760405162461bcd60e51b8152602060048201526015602482015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b60448201526064016104df565b50505b80610f3281611cde565b915050610c21565b50505050505050565b333014610f625760405162461bcd60e51b81526004016104df90611d68565b828114610f815760405162461bcd60e51b81526004016104df90611e75565b82610fbc5760405162461bcd60e51b815260206004820152600b60248201526a08adae0e8f240c4c2e8c6d60ab1b60448201526064016104df565b60005b83811015611120576000858583818110610fdb57610fdb611c92565b9050602002016020810190610ff09190611e9e565b6001600160a01b03160361103a5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b60448201526064016104df565b600085858381811061104e5761104e611c92565b90506020020160208101906110639190611e9e565b6001600160a01b031684848481811061107e5761107e611c92565b9050602002013560405160006040518083038185875af1925050503d80600081146110c5576040519150601f19603f3d011682016040523d82523d6000602084013e6110ca565b606091505b505090508061110d5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016104df565b508061111881611cde565b915050610fbf565b5050505050565b604080516000815260208101918290526002916111449190611eb9565b602060405180830381855afa158015611161573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111849190611eed565b81565b3330146111a65760405162461bcd60e51b81526004016104df90611d68565b816111e15760405162461bcd60e51b815260206004820152600b60248201526a456d70747920617272617960a81b60448201526064016104df565b600081116112015760405162461bcd60e51b81526004016104df90611d8a565b60025461120f908390611f06565b81111561122e5760405162461bcd60e51b81526004016104df90611dc1565b60005b82811015610b205783838281811061124b5761124b611c92565b905060200201356000036112965760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590818dbdb5b5a5d1b595b9d60721b60448201526064016104df565b60005b60025481101561132d578484838181106112b5576112b5611c92565b90506020020135600282815481106112cf576112cf611c92565b90600052602060002001540361131b5760405162461bcd60e51b8152602060048201526011602482015270436f6d6d69746d656e742065786973747360781b60448201526064016104df565b8061132581611cde565b915050611299565b5060005b818110156113bf5784848381811061134b5761134b611c92565b9050602002013585858381811061136457611364611c92565b90506020020135036113ad5760405162461bcd60e51b8152602060048201526012602482015271111d5c1b1a58d85d19481a5b881a5b9c1d5d60721b60448201526064016104df565b806113b781611cde565b915050611331565b5060028484838181106113d4576113d4611c92565b8354600181018555600094855260209485902091909402929092013591909201555083838281811061140857611408611c92565b905060200201357f33129f9e36e06e860f22ce83276273f4d83d31e9fd4a0d3a4dbac9d2da4f9d0d6001604051611443911515815260200190565b60405180910390a28061145581611cde565b915050611231565b60008061148a7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b905060006114b87f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185611f19565b604080518082018252848152602081018390529051632b0aac7f60e11b8152919250733333333C0A88F9BE4fd23ed0536F9B6c427e3B939163561558fe9161150291600401611f3b565b602060405180830381865af415801561151f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115439190611eed565b925050505b92915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561159c57602002820191906000526020600020905b815481526020019060010190808311611588575b5050505050905090565b6000805b6002548110156115f35782600282815481106115c8576115c8611c92565b9060005260206000200154036115e15750600192915050565b806115eb81611cde565b9150506115aa565b50600092915050565b60008061160a84600161145d565b604080516020808201849052863582840152868101356060808401919091528351808403909101815260808301845268756c747261686f6e6b60b81b60a08401528351608981850301815260a9840180865281519190930120600080845260c9909401948590529495509391927f0000000000000000000000000000000000000000000000000000000000000000916002916116a69190611eb9565b602060405180830381855afa1580156116c3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906116e69190611eed565b8480519060200120604051602001611717949392919093845260208401929092526040830152606082015260800190565b6040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a78f9e3686606001358760400135848980608001906117799190611f6c565b8b60a001358c60c001356040518863ffffffff1660e01b81526004016117a59796959493929190611fb6565b602060405180830381865afa1580156117c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e69190611ecb565b9695505050505050565b80356001600160a01b038116811461180757600080fd5b919050565b60008083601f84011261181e57600080fd5b50813567ffffffffffffffff81111561183657600080fd5b6020830191508360208260051b850101111561185157600080fd5b9250929050565b600080600080600080600060a0888a03121561187357600080fd5b87359650611883602089016117f0565b955060408801359450606088013567ffffffffffffffff808211156118a757600080fd5b818a0191508a601f8301126118bb57600080fd5b8135818111156118ca57600080fd5b8b60208285010111156118dc57600080fd5b6020830196508095505060808a01359150808211156118fa57600080fd5b506119078a828b0161180c565b989b979a50959850939692959293505050565b60005b8381101561193557818101518382015260200161191d565b50506000910152565b6000815180845261195681602086016020860161191a565b601f01601f19169290920160200192915050565b60208152600061197d602083018461193e565b9392505050565b60006020828403121561199657600080fd5b5035919050565b6000806000604084860312156119b257600080fd5b833567ffffffffffffffff8111156119c957600080fd5b6119d58682870161180c565b909790965060209590950135949350505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611a1557600080fd5b84359350611a25602086016117f0565b925060408501359150606085013567ffffffffffffffff80821115611a4957600080fd5b818701915087601f830112611a5d57600080fd5b813581811115611a6f57611a6f6119e9565b604051601f8201601f19908116603f01168101908382118183101715611a9757611a976119e9565b816040528281528a6020848701011115611ab057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060008060008060608789031215611aed57600080fd5b863567ffffffffffffffff80821115611b0557600080fd5b611b118a838b0161180c565b90985096506020890135915080821115611b2a57600080fd5b611b368a838b0161180c565b90965094506040890135915080821115611b4f57600080fd5b50611b5c89828a0161180c565b979a9699509497509295939492505050565b60008060008060408587031215611b8457600080fd5b843567ffffffffffffffff80821115611b9c57600080fd5b611ba88883890161180c565b90965094506020870135915080821115611bc157600080fd5b50611bce8782880161180c565b95989497509550505050565b60008060408385031215611bed57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611c3457835183529284019291840191600101611c18565b50909695505050505050565b60006bffffffffffffffffffffffff19808a60601b168352886014840152876034840152808760601b166054840152508460688301528284608884013750600091016088019081529695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112611cbe57600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cf057611cf0611cc8565b5060010190565b8183823760009101908152919050565b6001600160a01b0386168152602081018590526080604082018190528101839052828460a0830137600060a084830101526000601f19601f850116820160a0838203016060840152611d5c60a082018561193e565b98975050505050505050565b6020808252600890820152672737ba1029b2b63360c11b604082015260600190565b6020808252601e908201527f4d757374206265206e6f6e2d7a65726f20736967732072657175697265640000604082015260600190565b6020808252601690820152750a6d2cee640e4cae2ead2e4cac840e8dede40d0d2ced60531b604082015260600190565b8181038181111561154857611548611cc8565b634e487b7160e01b600052603160045260246000fd5b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152808660601b166054840152508360688301528251611e6381608885016020870161191a565b91909101608801979650505050505050565b6020808252600f908201526e098cadccee8d040dad2e6dac2e8c6d608b1b604082015260600190565b600060208284031215611eb057600080fd5b61197d826117f0565b60008251611cbe81846020870161191a565b600060208284031215611edd57600080fd5b8151801515811461197d57600080fd5b600060208284031215611eff57600080fd5b5051919050565b8082018082111561154857611548611cc8565b600082611f3657634e487b7160e01b600052601260045260246000fd5b500690565b60408101818360005b6002811015611f63578151835260209283019290910190600101611f44565b50505092915050565b6000808335601e19843603018112611f8357600080fd5b83018035915067ffffffffffffffff821115611f9e57600080fd5b6020019150600581901b360382131561185157600080fd5b87815286602082015285604082015260c060608201528360c0820152600060018060fb1b03851115611fe757600080fd5b8460051b808760e085013760808301949094525060a08101919091520160e0019594505050505056fea264697066735822122035707b238d9e073c337aa487cf73f97381952577d4eaa9e646e3b4b91b73143c64736f6c63430008140033"; diff --git a/packages/shared/src/contracts/contracts-config.ts b/packages/shared/src/contracts/contracts-config.ts index 0b8f6400..d48fc81c 100644 --- a/packages/shared/src/contracts/contracts-config.ts +++ b/packages/shared/src/contracts/contracts-config.ts @@ -3,28 +3,28 @@ export const CONTRACT_CONFIG_BY_CHAIN_ID = { // Horizen testnet zkVerifyAddress: "0xCC02D0A54F3184dF4c88811E5b9FAb7ff8131e4a", vkHash: - "0x80aca2e84f244400a76040aa5c77f9d83ff8409a2bf0d0cde96daffcf0a50e1b", + "0xb3c5381523a496996868370791ec7ae490be7e2c996296fb67708daed8a6ea38", poseidonT3Address: "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93", }, 84532: { // Base Sepolia zkVerifyAddress: "0x0807C544D38aE7729f8798388d89Be6502A1e8A8", vkHash: - "0x80aca2e84f244400a76040aa5c77f9d83ff8409a2bf0d0cde96daffcf0a50e1b", + "0xb3c5381523a496996868370791ec7ae490be7e2c996296fb67708daed8a6ea38", poseidonT3Address: "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93", }, 26514: { // Horizen mainnet zkVerifyAddress: "0xCb47A3C3B9Eb2E549a3F2EA4729De28CafbB2b69", vkHash: - "0x80aca2e84f244400a76040aa5c77f9d83ff8409a2bf0d0cde96daffcf0a50e1b", + "0xb3c5381523a496996868370791ec7ae490be7e2c996296fb67708daed8a6ea38", poseidonT3Address: "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93", }, 8453: { // Base mainnet zkVerifyAddress: "0xCb47A3C3B9Eb2E549a3F2EA4729De28CafbB2b69", vkHash: - "0x80aca2e84f244400a76040aa5c77f9d83ff8409a2bf0d0cde96daffcf0a50e1b", + "0xb3c5381523a496996868370791ec7ae490be7e2c996296fb67708daed8a6ea38", poseidonT3Address: "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93", }, } as const; diff --git a/packages/shared/src/types/account.ts b/packages/shared/src/types/account.ts index 3f835aa9..17ab1583 100644 --- a/packages/shared/src/types/account.ts +++ b/packages/shared/src/types/account.ts @@ -10,6 +10,7 @@ export interface Account { name: string; threshold: number; chainId: number; + contractVersion: number; createdAt: string; updatedAt: string; signers: AccountSigner[]; From a557e55c1d000c089f8a75ed8ea805dcf4f1c59b Mon Sep 17 00:00:00 2001 From: BoHsuu Date: Fri, 3 Apr 2026 16:09:15 +0700 Subject: [PATCH 2/2] refactor: extract shared account formatter and replace magic numbers with constant --- .../backend/src/account/account.service.ts | 15 +++++++++------ packages/backend/src/auth/auth.service.ts | 8 ++++++-- packages/backend/src/user/user.service.ts | 18 ++++-------------- .../backend/src/zkverify/zkverify.service.ts | 9 ++++++--- packages/backend/test/utils/proof.util.ts | 5 +++-- packages/nextjs/hooks/app/useGenerateProof.ts | 4 ++-- packages/shared/src/constants/contract.ts | 1 + packages/shared/src/constants/index.ts | 1 + 8 files changed, 32 insertions(+), 29 deletions(-) create mode 100644 packages/shared/src/constants/contract.ts diff --git a/packages/backend/src/account/account.service.ts b/packages/backend/src/account/account.service.ts index 36d7a04f..a84146aa 100644 --- a/packages/backend/src/account/account.service.ts +++ b/packages/backend/src/account/account.service.ts @@ -9,6 +9,7 @@ import { CreateAccountDto, CreateAccountBatchDto, UpdateAccountDto, + ULTRAHONK_CONTRACT_VERSION, } from '@polypay/shared'; import { RelayerService } from '@/relayer-wallet/relayer-wallet.service'; import { EventsService } from '@/events/events.service'; @@ -86,7 +87,7 @@ export class AccountService { name: dto.name, threshold: dto.threshold, chainId: dto.chainId, - contractVersion: 2, + contractVersion: ULTRAHONK_CONTRACT_VERSION, }, }); @@ -236,7 +237,7 @@ export class AccountService { name: dto.name, threshold: dto.threshold, chainId: deployment.chainId, - contractVersion: 2, + contractVersion: ULTRAHONK_CONTRACT_VERSION, }, }); @@ -301,7 +302,7 @@ export class AccountService { } return createdAccounts.map((account) => - this.formatAccountResponse(account), + AccountService.formatAccountResponse(account), ); } @@ -324,7 +325,7 @@ export class AccountService { throw new NotFoundException('Account not found'); } - return this.formatAccountResponse(account); + return AccountService.formatAccountResponse(account); } /** @@ -342,10 +343,12 @@ export class AccountService { orderBy: { createdAt: 'desc' }, }); - return accounts.map((account) => this.formatAccountResponse(account)); + return accounts.map((account) => + AccountService.formatAccountResponse(account), + ); } - private formatAccountResponse(account: { + static formatAccountResponse(account: { id: string; address: string; name: string | null; diff --git a/packages/backend/src/auth/auth.service.ts b/packages/backend/src/auth/auth.service.ts index 1ce52054..bf9f556d 100644 --- a/packages/backend/src/auth/auth.service.ts +++ b/packages/backend/src/auth/auth.service.ts @@ -1,7 +1,11 @@ import { Injectable, UnauthorizedException, Logger } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { ZkVerifyService } from '@/zkverify/zkverify.service'; -import { LoginDto, RefreshDto } from '@polypay/shared'; +import { + LoginDto, + RefreshDto, + ULTRAHONK_CONTRACT_VERSION, +} from '@polypay/shared'; import { PrismaService } from '@/database/prisma.service'; import { ConfigService } from '@nestjs/config'; import { CONFIG_KEYS } from '@/config/config.keys'; @@ -38,7 +42,7 @@ export class AuthService { }, 'auth', undefined, - 2, + ULTRAHONK_CONTRACT_VERSION, ); } catch (error) { this.logger.error(`Proof verification failed: ${error.message}`); diff --git a/packages/backend/src/user/user.service.ts b/packages/backend/src/user/user.service.ts index f7208f8d..1da3904f 100644 --- a/packages/backend/src/user/user.service.ts +++ b/packages/backend/src/user/user.service.ts @@ -6,6 +6,7 @@ import { } from '@nestjs/common'; import { PrismaService } from '@/database/prisma.service'; import { CreateUserDto } from '@polypay/shared'; +import { AccountService } from '@/account/account.service'; @Injectable() export class UserService { @@ -75,20 +76,9 @@ export class UserService { }, }); - return accounts.map((account) => ({ - id: account.id, - address: account.address, - name: account.name, - threshold: account.threshold, - chainId: account.chainId, - contractVersion: account.contractVersion, - createdAt: account.createdAt, - signers: account.signers.map((signer) => ({ - commitment: signer.user.commitment, - name: signer.displayName, - isCreator: signer.isCreator, - })), - })); + return accounts.map((account) => + AccountService.formatAccountResponse(account), + ); } /** diff --git a/packages/backend/src/zkverify/zkverify.service.ts b/packages/backend/src/zkverify/zkverify.service.ts index cf32eb38..860fdc39 100644 --- a/packages/backend/src/zkverify/zkverify.service.ts +++ b/packages/backend/src/zkverify/zkverify.service.ts @@ -12,6 +12,7 @@ import { horizenTestnet, NetworkType, NetworkValue, + ULTRAHONK_CONTRACT_VERSION, } from '@polypay/shared'; import { CONFIG_KEYS } from '@/config/config.keys'; import { @@ -25,7 +26,9 @@ import { export type CircuitType = 'transaction' | 'auth'; function getProofType(contractVersion: number): string { - return contractVersion >= 2 ? 'ultrahonk' : 'ultraplonk'; + return contractVersion >= ULTRAHONK_CONTRACT_VERSION + ? 'ultrahonk' + : 'ultraplonk'; } function bytesToHex(bytes: Uint8Array): string { @@ -141,7 +144,7 @@ export class ZkVerifyService { let params: Record; - if (contractVersion >= 2) { + if (contractVersion >= ULTRAHONK_CONTRACT_VERSION) { // UltraHonk: hex proof + separate publicSignals params = { proofType, @@ -255,7 +258,7 @@ export class ZkVerifyService { let params: Record; - if (contractVersion >= 2) { + if (contractVersion >= ULTRAHONK_CONTRACT_VERSION) { // UltraHonk: hex VK const hexVk = typeof vk === 'string' && !vk.startsWith('0x') ? `0x${vk}` : vk; diff --git a/packages/backend/test/utils/proof.util.ts b/packages/backend/test/utils/proof.util.ts index 77f29e23..dd75c88d 100644 --- a/packages/backend/test/utils/proof.util.ts +++ b/packages/backend/test/utils/proof.util.ts @@ -6,6 +6,7 @@ import { hexToByteArray, getPublicKeyXY, BN254_MODULUS, + ULTRAHONK_CONTRACT_VERSION, } from '@polypay/shared'; import { TestSigner, signRawMessage } from './signer.util'; @@ -60,7 +61,7 @@ export async function generateTestProof( signer: TestSigner, secret: bigint, txHash: Hex, - contractVersion: number = 2, + contractVersion: number = ULTRAHONK_CONTRACT_VERSION, ): Promise { // 1. Sign txHash (local signing, no RPC) const signature = await signRawMessage(signer, txHash); @@ -109,7 +110,7 @@ export async function generateTestProof( let publicInputs: string[]; let vk: string | undefined; - if (contractVersion >= 2) { + if (contractVersion >= ULTRAHONK_CONTRACT_VERSION) { const { UltraHonkBackend } = await import('@aztec/bb.js'); const backend = new UltraHonkBackend(bytecode); ({ proof, publicInputs } = await backend.generateProof(witness, { keccak: true })); diff --git a/packages/nextjs/hooks/app/useGenerateProof.ts b/packages/nextjs/hooks/app/useGenerateProof.ts index 94ff0ec9..dd769cc2 100644 --- a/packages/nextjs/hooks/app/useGenerateProof.ts +++ b/packages/nextjs/hooks/app/useGenerateProof.ts @@ -3,7 +3,7 @@ import { useCallback } from "react"; import { useMetaMultiSigWallet } from "./useMetaMultiSigWallet"; import { useNetworkGuard } from "./useNetworkGuard"; -import { getPublicKeyXY, hexToByteArray, poseidonHash2 } from "@polypay/shared"; +import { ULTRAHONK_CONTRACT_VERSION, getPublicKeyXY, hexToByteArray, poseidonHash2 } from "@polypay/shared"; import { type Hex } from "viem"; import { useAccount, useWalletClient } from "wagmi"; import { useAccountStore } from "~~/services/store"; @@ -117,7 +117,7 @@ export function useGenerateProof(options?: UseGenerateProofOptions) { let publicInputs: string[]; let vk: string | undefined; - if (currentAccount?.contractVersion && currentAccount.contractVersion >= 2) { + if (currentAccount?.contractVersion && currentAccount.contractVersion >= ULTRAHONK_CONTRACT_VERSION) { const { UltraHonkBackend } = await import("@aztec/bb.js"); const backend = new UltraHonkBackend(bytecode, { threads: 2 }); ({ proof, publicInputs } = await backend.generateProof(execResult.witness, { keccak: true })); diff --git a/packages/shared/src/constants/contract.ts b/packages/shared/src/constants/contract.ts new file mode 100644 index 00000000..71352fa2 --- /dev/null +++ b/packages/shared/src/constants/contract.ts @@ -0,0 +1 @@ +export const ULTRAHONK_CONTRACT_VERSION = 2; diff --git a/packages/shared/src/constants/index.ts b/packages/shared/src/constants/index.ts index e07a903a..c63b2893 100644 --- a/packages/shared/src/constants/index.ts +++ b/packages/shared/src/constants/index.ts @@ -2,3 +2,4 @@ export * from "./socket-events"; export * from "./room"; export * from "./token"; export * from "./campaign"; +export * from "./contract";