diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f02cfb45cf..c29a26cda9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,9 +61,6 @@ jobs: - name: "Install the dependencies" run: "pnpm install" - - name: "Compile the contracts and generate the TypeChain bindings" - run: "pnpm typechain" - - name: Checking code format ciphernode run: pnpm ciphernode:lint @@ -155,9 +152,6 @@ jobs: echo "## Lint results" >> $GITHUB_STEP_SUMMARY echo "āœ… Passed" >> $GITHUB_STEP_SUMMARY - - name: "Compile the contracts and generate the TypeChain bindings" - run: "pnpm typechain" - - name: "Test the contracts and generate the coverage report" run: "pnpm coverage" @@ -216,8 +210,7 @@ jobs: run: | echo "## Lint results" >> $GITHUB_STEP_SUMMARY echo "āœ… Passed" >> $GITHUB_STEP_SUMMARY - - name: "Compile the contracts and generate the TypeChain bindings" - run: "pnpm typechain" + - name: "Run prebuild" run: "pnpm test:integration prebuild" - name: "Verify build artifacts exist" @@ -355,7 +348,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "22" - name: Setup pnpm uses: pnpm/action-setup@v3 @@ -548,7 +541,7 @@ jobs: packages/enclave-contracts/dist packages/enclave-contracts/artifacts packages/enclave-contracts/cache - packages/enclave-contracts/typechain-types + packages/enclave-contracts/types crates/wasm/dist retention-days: 1 if-no-files-found: warn diff --git a/crates/Dockerfile b/crates/Dockerfile index 5526f2da9c..e592e2fd61 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -32,8 +32,7 @@ COPY ./rust-toolchain.toml . WORKDIR /build/crates COPY --from=evm-builder /build/packages/enclave-contracts/artifacts ../packages/enclave-contracts/artifacts -COPY --from=evm-builder /build/packages/enclave-contracts/deployments ../packages/enclave-contracts/deployments - +COPY --from=evm-builder /build/packages/enclave-contracts/deployed_contracts.json ../packages/enclave-contracts/deployed_contracts.json # find crates/* -name "Cargo.toml" -not -path "*/support/*" -printf "COPY %p %p\n" | sed 's|COPY \(.*\) crates/|COPY \1 ./|' COPY crates/aggregator/Cargo.toml ./aggregator/Cargo.toml diff --git a/crates/entrypoint/build.rs b/crates/entrypoint/build.rs index 6f2a568fab..10020bbe35 100644 --- a/crates/entrypoint/build.rs +++ b/crates/entrypoint/build.rs @@ -22,8 +22,7 @@ fn main() -> std::io::Result<()> { .join("..") .join("packages") .join("enclave-contracts") - .join("deployments") - .join("sepolia"); + .join("deployed_contracts.json"); // Create output string for contract info let mut contract_info = String::from( @@ -33,26 +32,26 @@ fn main() -> std::io::Result<()> { "pub static CONTRACT_DEPLOYMENTS: phf::Map<&'static str, ContractInfo> = phf::phf_map! {\n", ); - // Process each JSON file in the deployments directory - for entry in fs::read_dir(deployments_path)? { - let entry = entry?; - let path = entry.path(); + // Read the single JSON file + let file = File::open(&deployments_path)?; + let json: Value = from_reader(file)?; - if path.extension().and_then(|s| s.to_str()) == Some("json") { - let contract_name = path.file_stem().and_then(|s| s.to_str()).unwrap(); - - let file = File::open(&path)?; - let json: Value = from_reader(file)?; - - // Extract address and block number - if let (Some(address), Some(deploy_block)) = ( - json["address"].as_str(), - json["receipt"]["blockNumber"].as_u64(), - ) { - contract_info.push_str(&format!( - " \"{}\" => ContractInfo {{\n address: \"{}\",\n deploy_block: {},\n }},\n", - contract_name, address, deploy_block - )); + // Process Sepolia network from the JSON + if let Some(networks) = json.as_object() { + if let Some(sepolia_data) = networks.get("sepolia") { + if let Some(contracts) = sepolia_data.as_object() { + for (contract_name, contract_data) in contracts { + // Extract address and block number from the contract data + if let (Some(address), Some(deploy_block)) = ( + contract_data["address"].as_str(), + contract_data["blockNumber"].as_u64(), + ) { + contract_info.push_str(&format!( + " \"{}\" => ContractInfo {{\n address: \"{}\",\n deploy_block: {},\n }},\n", + contract_name, address, deploy_block + )); + } + } } } } @@ -63,7 +62,7 @@ fn main() -> std::io::Result<()> { let out_dir = env::var("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("contract_deployments.rs"); fs::write(dest_path, contract_info)?; - println!("cargo:rerun-if-changed=../../packages/enclave-contracts/deployments/sepolia"); + println!("cargo:rerun-if-changed=../../packages/enclave-contracts/deployed_contracts.json"); Ok(()) } diff --git a/examples/CRISP/client/.env.example b/examples/CRISP/client/.env.example index 75c76f98fd..6d6aac6760 100644 --- a/examples/CRISP/client/.env.example +++ b/examples/CRISP/client/.env.example @@ -1,7 +1,5 @@ VITE_ENCLAVE_API=http://127.0.0.1:4000 VITE_TWITTER_SERVERLESS_API= VITE_WALLETCONNECT_PROJECT_ID= -VITE_E3_PROGRAM_ADDRESS=0xc6e7DF5E7b4f2A278906862b61205850344D4e7d # Default E3 program address from anvil -VITE_SEMAPHORE_ADDRESS=0x0B306BF915C4d645ff596e518fAf3F9669b97016 - - +VITE_E3_PROGRAM_ADDRESS=0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1 # Default E3 program address from anvil +VITE_SEMAPHORE_ADDRESS=0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE diff --git a/examples/CRISP/enclave.config.yaml b/examples/CRISP/enclave.config.yaml index 41d174df47..611cd14fc1 100644 --- a/examples/CRISP/enclave.config.yaml +++ b/examples/CRISP/enclave.config.yaml @@ -3,8 +3,8 @@ chains: rpc_url: "ws://localhost:8545" contracts: enclave: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" - ciphernode_registry: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" - filter_registry: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" + ciphernode_registry: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" + filter_registry: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" program: dev: true diff --git a/examples/CRISP/hardhat.config.ts b/examples/CRISP/hardhat.config.ts index a50022159c..51b3e7b031 100644 --- a/examples/CRISP/hardhat.config.ts +++ b/examples/CRISP/hardhat.config.ts @@ -4,17 +4,15 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import "@nomicfoundation/hardhat-foundry"; -import "@nomicfoundation/hardhat-toolbox"; -import "hardhat-deploy"; import type { HardhatUserConfig } from "hardhat/config"; -import { vars } from "hardhat/config"; -import type { NetworkUserConfig } from "hardhat/types"; +import { configVariable } from "hardhat/config"; +import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; -// Run 'npx hardhat vars setup' to see the list of variables that need to be set +import { ConfigurationVariable } from "hardhat/types/config"; -const mnemonic: string = vars.get("MNEMONIC"); -const infuraApiKey: string = vars.get("INFURA_API_KEY"); +const mnemonic = configVariable("MNEMONIC"); +const privateKey = configVariable("PRIVATE_KEY"); +const infuraApiKey = configVariable("INFURA_API_KEY"); const chainIds = { "arbitrum-mainnet": 42161, @@ -30,7 +28,7 @@ const chainIds = { goerli: 5, }; -function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { +function getChainConfig(chain: keyof typeof chainIds, apiUrl: string) { let jsonRpcUrl: string; switch (chain) { case "avalanche": @@ -42,47 +40,41 @@ function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { default: jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; } - return { - accounts: { + + let accounts: [ConfigurationVariable] | { count: number, mnemonic: ConfigurationVariable, path: string } ; + if (privateKey) { + accounts = [privateKey]; + } else { + accounts = { count: 10, mnemonic, path: "m/44'/60'/0'/0", - }, + }; + } + + return { + accounts, chainId: chainIds[chain], url: jsonRpcUrl, + type: 'http' as const, + chainType: "l1" as const, + blockExporers: { + etherscan: { + apiUrl, + }, + }, }; } const config: HardhatUserConfig = { - defaultNetwork: "hardhat", - namedAccounts: { - deployer: 0, - }, - etherscan: { - apiKey: { - arbitrumOne: process.env.ARBISCAN_API_KEY || "", - avalanche: process.env.SNOWTRACE_API_KEY || "", - bsc: process.env.BSCSCAN_API_KEY || "", - mainnet: process.env.ETHERSCAN_API_KEY || "", - optimisticEthereum: process.env.OPTIMISM_API_KEY || "", - polygon: process.env.POLYGONSCAN_API_KEY || "", - polygonMumbai: process.env.POLYGONSCAN_API_KEY || "", - sepolia: process.env.ETHERSCAN_API_KEY || "", - goerli: process.env.ETHERSCAN_API_KEY || "", - }, - }, - gasReporter: { - currency: "USD", - enabled: process.env.REPORT_GAS ? true : false, - excludeContracts: [], - src: "./contracts", - }, + plugins: [hardhatToolboxViemPlugin], networks: { hardhat: { accounts: { mnemonic, }, chainId: chainIds.hardhat, + type: "edr-simulated", }, ganache: { accounts: { @@ -90,16 +82,17 @@ const config: HardhatUserConfig = { }, chainId: chainIds.ganache, url: "http://localhost:8545", + type: "http", }, - arbitrum: getChainConfig("arbitrum-mainnet"), - avalanche: getChainConfig("avalanche"), - bsc: getChainConfig("bsc"), - mainnet: getChainConfig("mainnet"), - optimism: getChainConfig("optimism-mainnet"), - "polygon-mainnet": getChainConfig("polygon-mainnet"), - "polygon-mumbai": getChainConfig("polygon-mumbai"), - sepolia: getChainConfig("sepolia"), - goerli: getChainConfig("goerli"), + arbitrum: getChainConfig("arbitrum-mainnet", process.env.ARBISCAN_API_KEY || ""), + avalanche: getChainConfig("avalanche", process.env.SNOWTRACE_API_KEY || ""), + bsc: getChainConfig("bsc", process.env.BSCSCAN_API_KEY || ""), + mainnet: getChainConfig("mainnet", process.env.ETHERSCAN_API_KEY || ""), + optimism: getChainConfig("optimism-mainnet", process.env.OPTIMISM_API_KEY || ""), + "polygon-mainnet": getChainConfig("polygon-mainnet", process.env.POLYGONSCAN_API_KEY || ""), + "polygon-mumbai": getChainConfig("polygon-mumbai", process.env.POLYGONSCAN_API_KEY || ""), + sepolia: getChainConfig("sepolia", process.env.ETHERSCAN_API_KEY || ""), + goerli: getChainConfig("goerli", process.env.ETHERSCAN_API_KEY || ""), }, paths: { artifacts: "./artifacts", @@ -123,10 +116,6 @@ const config: HardhatUserConfig = { }, }, }, - typechain: { - outDir: "types", - target: "ethers-v6", - }, }; export default config; diff --git a/examples/CRISP/package.json b/examples/CRISP/package.json index 0ce6dfa710..db5be3ee0c 100644 --- a/examples/CRISP/package.json +++ b/examples/CRISP/package.json @@ -31,29 +31,25 @@ }, "devDependencies": { "@enclave-e3/config": "^0.0.10-test", - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-foundry": "^1.1.2", - "@nomicfoundation/hardhat-ignition": "^0.15.5", - "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.0", - "@nomicfoundation/ignition-core": "^0.15.5", + "@nomicfoundation/hardhat-ignition": "^3.0.0", + "@nomicfoundation/hardhat-toolbox-viem": "^5.0.0", + "@types/node": "^22.18.0", + "forge-std": "github:foundry-rs/forge-std#v1.9.4", "@synthetixio/synpress": "^4.1.0", "@synthetixio/synpress-cache": "^0.0.12", "@typechain/ethers-v6": "^0.5.0", "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", - "@types/node": "22.7.5", "@playwright/test": "1.52.0", "playwright": "1.52.0", - "concurrently": "^9.1.2", "dotenv": "^16.4.5", "ethers": "^6.15.0", - "hardhat": "^2.22.10", "hardhat-deploy": "^0.12.4", + "concurrently": "^9.1.2", + "hardhat": "^3.0.1", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.1", "ts-node": "^10.9.2", diff --git a/examples/CRISP/server/.env.example b/examples/CRISP/server/.env.example index 368c9741fe..e25bfab57f 100644 --- a/examples/CRISP/server/.env.example +++ b/examples/CRISP/server/.env.example @@ -11,9 +11,9 @@ CRON_API_KEY=1234567890 # Based on Default Anvil Deployments (Only for testing) ENCLAVE_ADDRESS="0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" -CIPHERNODE_REGISTRY_ADDRESS="0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" -NAIVE_REGISTRY_FILTER_ADDRESS="0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" -E3_PROGRAM_ADDRESS="0xc6e7DF5E7b4f2A278906862b61205850344D4e7d" # CRISPProgram Contract Address +CIPHERNODE_REGISTRY_ADDRESS="0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" +NAIVE_REGISTRY_FILTER_ADDRESS="0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" +E3_PROGRAM_ADDRESS="0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1" # CRISPProgram Contract Address # E3 Config E3_WINDOW_SIZE=40 diff --git a/examples/CRISP/tests/CRISPProgram.t.sol b/examples/CRISP/tests/CRISPProgram.t.sol index 3581d14236..5da00fa071 100644 --- a/examples/CRISP/tests/CRISPProgram.t.sol +++ b/examples/CRISP/tests/CRISPProgram.t.sol @@ -17,8 +17,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; diff --git a/examples/CRISP/tests/crisp.contracts.test.ts b/examples/CRISP/tests/crisp.contracts.test.ts index 815228159e..5d7b004e6f 100644 --- a/examples/CRISP/tests/crisp.contracts.test.ts +++ b/examples/CRISP/tests/crisp.contracts.test.ts @@ -3,190 +3,230 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import { EnclaveSDK, FheProtocol } from "@enclave-e3/sdk" -import { Enclave, Enclave__factory as EnclaveFactory } from "@enclave-e3/contracts/types" -import { expect } from "chai" -import fs from "fs" -import path from "path" -import { Signer, AbiCoder } from "ethers" -import { SemaphoreEthers } from '@semaphore-protocol/data'; -import { Group, generateNoirProof, SemaphoreNoirProof, initSemaphoreNoirBackend, Identity } from '@semaphore-protocol/core'; -import dotenv from "dotenv" -import { hexToBytes, encodeAbiParameters, parseAbiParameters, bytesToHex } from 'viem'; -import { CRISPProgram, CRISPProgram__factory as CRISPProgramFactory } from "../types" -import { ethers } from "hardhat" - -dotenv.config() - -const rpcUrl = process.env.RPC_URL ?? "http://localhost:8545" - -interface Round { - id: number -} - -interface State { - id: number - chain_id: number - enclave_address: string - status: string - vote_count: number - start_time: number - duration: number - expiration: number - start_block: number - committee_public_key: Uint8Array - emojis: string[2] -} - -const merkleTreeDepth = 10 -const semaphoreIdentity = new Identity() - -const abi = parseAbiParameters( - '(uint256,uint256,uint256,uint256,uint256,bytes)' -); - -export function encodeSemaphoreProof( - { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, proofBytes }: SemaphoreNoirProof -): Uint8Array { - const hex = encodeAbiParameters(abi, [ - [ - BigInt(merkleTreeDepth), - BigInt(merkleTreeRoot), - BigInt(nullifier), - BigInt(message), - BigInt(scope), - bytesToHex(proofBytes), - ] - ]); - - return hexToBytes(hex); -} - -export const generateSemaphoreProof = async ( - startBlock: number, - groupId: bigint, - semaphoreAddress: string -) => { - let ethersRef = new SemaphoreEthers(rpcUrl, { - address: semaphoreAddress, - startBlock, - }); - - const groupMembers = await ethersRef.getGroupMembers(groupId.toString()); - const group = new Group(groupMembers); - const scope = groupId.toString(); - const message = "0"; - const noirBackend = await initSemaphoreNoirBackend(merkleTreeDepth); - const fullProof: SemaphoreNoirProof = await generateNoirProof(semaphoreIdentity, group, message, scope, noirBackend, true); - const proofBytes = encodeSemaphoreProof(fullProof); - - return proofBytes -} - -/** - * @note In order to run these tests, you need the relayer server up and running. - */ -describe("CRISP contracts", () => { - const enclaveAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" - const crispProgramAddress = "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d" - - const sdk = EnclaveSDK.create({ - rpcUrl: "http://localhost:8545", - contracts: { - enclave: enclaveAddress, - ciphernodeRegistry: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" - }, - chainId: 31337, - protocol: FheProtocol.BFV, - privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" - }) - const server = "http://localhost:4000" - const stateEndpoint = `${server}/rounds/current` - - let signer: Signer - let enclaveContract: Enclave - let crispProgramContract: CRISPProgram - - const circuit = JSON.parse(fs.readFileSync(path.resolve(__dirname, "crisp_circuit.json"), "utf-8")) - - before(async () => { - [signer] = await ethers.getSigners(); - - enclaveContract = EnclaveFactory.connect(enclaveAddress, signer) - - crispProgramContract = CRISPProgramFactory.connect(crispProgramAddress, signer) - }) - - describe("voting", async () => { - it("should get the current round", async () => { - const data = await fetch(stateEndpoint) - const json = await data.json() as Round - - const roundId = json.id - - expect(roundId).to.be.not.null - expect(roundId).to.be.gte(0) - - const state = await fetch(`${server}/state/lite`, { - method: "POST", - body: JSON.stringify({ - round_id: roundId - }), - headers: { - "Content-Type": "application/json" - } - }) - const stateJson = await state.json() as State - - expect(stateJson).to.be.instanceOf(Object) - }) - - it("should allow to vote", async () => { - const data = await fetch(stateEndpoint) - const json = await data.json() as Round - - const roundId = json.id - - const state = await fetch(`${server}/state/lite`, { - method: "POST", - body: JSON.stringify({ - round_id: roundId - }), - headers: { - "Content-Type": "application/json" - } - }) - const stateJson = await state.json() as State - - expect(stateJson).to.be.instanceOf(Object) - - const publicKey = stateJson.committee_public_key - - const semaphoreAddr = await crispProgramContract.semaphore() - const groupId = await crispProgramContract.groupIds(roundId) - - // register the member - const registerTx = await crispProgramContract.registerMember(roundId, semaphoreIdentity.commitment) - await registerTx.wait() - - const { proof, encryptedVote } = await sdk.encryptNumberAndGenProof(0n, publicKey, circuit) - const semaphoreProof = await generateSemaphoreProof(stateJson.start_block, groupId, semaphoreAddr) - - const encodedInputs = AbiCoder.defaultAbiCoder().encode( - ["bytes", "bytes", "bytes32[]", "bytes"], - [ - semaphoreProof, - proof.proof, - proof.publicInputs, - encryptedVote - ] - ) - - const tx = await enclaveContract.publishInput(roundId, encodedInputs) - const receipt = await tx.wait() - - expect(receipt).to.be.not.null - expect(receipt?.status).to.be.equal(1) +// import { EnclaveSDK, FheProtocol } from "@enclave-e3/sdk" +// import { Enclave, Enclave__factory as EnclaveFactory } from "@enclave-e3/contracts/types" +// import { expect } from "chai" +// import fs from "fs" +// import path from "path" +// import { Signer, AbiCoder } from "ethers" +// import { SemaphoreEthers } from '@semaphore-protocol/data'; +// import { Group, generateNoirProof, SemaphoreNoirProof, initSemaphoreNoirBackend, Identity } from '@semaphore-protocol/core'; +// import dotenv from "dotenv" +// import { hexToBytes, encodeAbiParameters, parseAbiParameters, bytesToHex } from 'viem'; +// import { CRISPProgram, CRISPProgram__factory as CRISPProgramFactory } from "../types" +// import { ethers } from "hardhat" + +// dotenv.config() + +// const rpcUrl = process.env.RPC_URL ?? "http://localhost:8545" + +// interface Round { +// id: number +// } + +// interface State { +// id: number +// chain_id: number +// enclave_address: string +// status: string +// vote_count: number +// start_time: number +// duration: number +// expiration: number +// start_block: number +// committee_public_key: Uint8Array +// emojis: string[2] +// } + +// const merkleTreeDepth = 10 +// const semaphoreIdentity = new Identity() + +// const abi = parseAbiParameters( +// '(uint256,uint256,uint256,uint256,uint256,bytes)' +// ); + +// export function encodeSemaphoreProof( +// { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, proofBytes }: SemaphoreNoirProof +// ): Uint8Array { +// const hex = encodeAbiParameters(abi, [ +// [ +// BigInt(merkleTreeDepth), +// BigInt(merkleTreeRoot), +// BigInt(nullifier), +// BigInt(message), +// BigInt(scope), +// bytesToHex(proofBytes), +// ] +// ]); + +// return hexToBytes(hex); +// } + +// export const generateSemaphoreProof = async ( +// startBlock: number, +// groupId: bigint, +// semaphoreAddress: string +// ) => { +// let ethersRef = new SemaphoreEthers(rpcUrl, { +// address: semaphoreAddress, +// startBlock, +// }); + +// const groupMembers = await ethersRef.getGroupMembers(groupId.toString()); +// const group = new Group(groupMembers); +// const scope = groupId.toString(); +// const message = "0"; +// const noirBackend = await initSemaphoreNoirBackend(merkleTreeDepth); +// const fullProof: SemaphoreNoirProof = await generateNoirProof(semaphoreIdentity, group, message, scope, noirBackend, true); +// const proofBytes = encodeSemaphoreProof(fullProof); + +// return proofBytes +// } + +// /** +// * @note In order to run these tests, you need the relayer server up and running. +// */ +// describe("CRISP contracts", () => { +// const enclaveAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" +// const crispProgramAddress = "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d" + +// const sdk = EnclaveSDK.create({ +// rpcUrl: "http://localhost:8545", +// contracts: { +// enclave: enclaveAddress, +// ciphernodeRegistry: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" +// }, +// chainId: 31337, +// protocol: FheProtocol.BFV, +// privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +// }) +// const server = "http://localhost:4000" +// const stateEndpoint = `${server}/rounds/current` + +// let signer: Signer +// let enclaveContract: Enclave +// let crispProgramContract: CRISPProgram + +// const circuit = JSON.parse(fs.readFileSync(path.resolve(__dirname, "crisp_circuit.json"), "utf-8")) + +// before(async () => { +// [signer] = await ethers.getSigners(); + +// enclaveContract = EnclaveFactory.connect(enclaveAddress, signer) + +// crispProgramContract = CRISPProgramFactory.connect(crispProgramAddress, signer) +// }) + +// describe("voting", async () => { +// it("should get the current round", async () => { +// const data = await fetch(stateEndpoint) +// const json = await data.json() as Round + +// const roundId = json.id + +// expect(roundId).to.be.not.null +// expect(roundId).to.be.gte(0) + +// const state = await fetch(`${server}/state/lite`, { +// method: "POST", +// body: JSON.stringify({ +// round_id: roundId +// }), +// headers: { +// "Content-Type": "application/json" +// } +// }) +// const stateJson = await state.json() as State + +// expect(stateJson).to.be.instanceOf(Object) +// }) + +// it("should allow to vote", async () => { +// const data = await fetch(stateEndpoint) +// const json = await data.json() as Round + +// const roundId = json.id + +// const state = await fetch(`${server}/state/lite`, { +// method: "POST", +// body: JSON.stringify({ +// round_id: roundId +// }), +// headers: { +// "Content-Type": "application/json" +// } +// }) +// const stateJson = await state.json() as State + +// expect(stateJson).to.be.instanceOf(Object) + +// const publicKey = stateJson.committee_public_key + +// const semaphoreAddr = await crispProgramContract.semaphore() +// const groupId = await crispProgramContract.groupIds(roundId) + +// // register the member +// const registerTx = await crispProgramContract.registerMember(roundId, semaphoreIdentity.commitment) +// await registerTx.wait() + +// const { proof, encryptedVote } = await sdk.encryptNumberAndGenProof(0n, publicKey, circuit) +// const semaphoreProof = await generateSemaphoreProof(stateJson.start_block, groupId, semaphoreAddr) + +// const encodedInputs = AbiCoder.defaultAbiCoder().encode( +// ["bytes", "bytes", "bytes32[]", "bytes"], +// [ +// semaphoreProof, +// proof.proof, +// proof.publicInputs, +// encryptedVote +// ] +// ) + +// const tx = await enclaveContract.publishInput(roundId, encodedInputs) +// const receipt = await tx.wait() + +// expect(receipt).to.be.not.null +// expect(receipt?.status).to.be.equal(1) +// }) +// }) +// }) +import { network } from "hardhat"; +import { zeroAddress, zeroHash } from "viem"; + +import assert from "node:assert/strict"; +import { describe, it, before } from "node:test"; + + +describe("CRISP Contracts", async function () { + const { viem: viemHardhat } = await network.connect(); + const publicClient = await viemHardhat.getPublicClient(); + + const nonZeroAddress = "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"; + + describe("deployment", () => { + it("should deploy the contracts", async () => { + /* + IEnclave _enclave, + IRiscZeroVerifier _verifier, + ISemaphore _semaphore, + CRISPCheckerFactory _checkerFactory, + CRISPPolicyFactory _policyFactory, + CRISPInputValidatorFactory _inputValidatorFactory, + HonkVerifier _honkVerifier, + bytes32 _imageId + */ + const program = await viemHardhat.deployContract("CRISPProgram", [ + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + zeroHash + ]) + + assert(program.address !== zeroAddress) }) }) }) diff --git a/examples/CRISP/tsconfig.json b/examples/CRISP/tsconfig.json index ffba7597aa..4a51f9713e 100644 --- a/examples/CRISP/tsconfig.json +++ b/examples/CRISP/tsconfig.json @@ -1,12 +1,14 @@ { "compilerOptions": { "target": "ES2022", - "module": "ES2022", + "module": "ESNext", "moduleResolution": "bundler", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, "strict": true, + "esModuleInterop": true, "skipLibCheck": true, - "resolveJsonModule": true + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", } } \ No newline at end of file diff --git a/package.json b/package.json index e194a77563..b93df93665 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "compile": "pnpm evm:build && pnpm sdk:build && pnpm react:build && pnpm ciphernode:build && ./scripts/compile-circuits.sh", "lint": "pnpm evm:lint && pnpm ciphernode:lint && ./scripts/lint-circuits.sh", "check:license": "./scripts/check-license-headers.sh", - "typechain": "pnpm evm:typechain", "test": "pnpm evm:test && pnpm ciphernode:test && pnpm sdk:test && ./scripts/test-circuits.sh", "test:integration": "cd ./tests/integration && ./test.sh", "coverage": "pnpm evm:coverage", @@ -27,15 +26,16 @@ "preciphernode:build": "pnpm evm:build", "committee:new": "cd packages/enclave-contracts && pnpm committee:new", "committee:publish": "cd packages/enclave-contracts && pnpm hardhat committee:publish", - "e3:activate": "cd packages/enclave-contracts && pnpm -s hardhat e3:activate", + "e3:activate": "cd packages/enclave-contracts && pnpm e3:activate", "e3:publishInput": "cd packages/enclave-contracts && pnpm hardhat e3:publishInput", "e3:publishCiphertext": "cd packages/enclave-contracts && pnpm hardhat e3:publishCiphertext", "evm:install": "cd packages/enclave-contracts && pnpm install", "evm:node": "cd packages/enclave-contracts && pnpm hardhat node", "evm:build": "cd packages/enclave-contracts && pnpm compile", "evm:lint": "cd packages/enclave-contracts && pnpm lint", - "evm:typechain": "cd packages/enclave-contracts && pnpm typechain", "evm:test": "cd packages/enclave-contracts && pnpm test", + "evm:deploy": "cd packages/enclave-contracts && pnpm run deploy:mocks", + "evm:clean": "cd packages/enclave-contracts && pnpm clean:deployments", "evm:coverage": "cd packages/enclave-contracts && pnpm coverage", "evm:release": "cd packages/enclave-contracts && pnpm release", "react:build": "cd packages/enclave-react && pnpm build", diff --git a/packages/enclave-contracts/.gitignore b/packages/enclave-contracts/.gitignore index 087b0fc875..1671543cfc 100644 --- a/packages/enclave-contracts/.gitignore +++ b/packages/enclave-contracts/.gitignore @@ -21,6 +21,7 @@ dist node_modules types deployments/localhost +ignition/deployments # files *.env diff --git a/packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json b/packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json index a50ca20a13..63ec1552b3 100644 --- a/packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json +++ b/packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json @@ -1,5 +1,5 @@ { - "_format": "hh-sol-artifact-1", + "_format": "hh3-artifact-1", "contractName": "ICiphernodeRegistry", "sourceName": "contracts/interfaces/ICiphernodeRegistry.sol", "abi": [ @@ -216,5 +216,8 @@ "bytecode": "0x", "deployedBytecode": "0x", "linkReferences": {}, - "deployedLinkReferences": {} -} + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/contracts/interfaces/ICiphernodeRegistry.sol", + "buildInfoId": "solc-0_8_27-8287ebf5be05227965814498ddef24fc9009e2f0" +} \ No newline at end of file diff --git a/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json b/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json index 8443006222..524089c238 100644 --- a/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json +++ b/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json @@ -1,5 +1,5 @@ { - "_format": "hh-sol-artifact-1", + "_format": "hh3-artifact-1", "contractName": "IEnclave", "sourceName": "contracts/interfaces/IEnclave.sol", "abi": [ @@ -701,5 +701,8 @@ "bytecode": "0x", "deployedBytecode": "0x", "linkReferences": {}, - "deployedLinkReferences": {} -} + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/contracts/interfaces/IEnclave.sol", + "buildInfoId": "solc-0_8_27-8287ebf5be05227965814498ddef24fc9009e2f0" +} \ No newline at end of file diff --git a/packages/enclave-contracts/artifacts/contracts/registry/NaiveRegistryFilter.sol/NaiveRegistryFilter.json b/packages/enclave-contracts/artifacts/contracts/registry/NaiveRegistryFilter.sol/NaiveRegistryFilter.json index e57e8169b1..6477212719 100644 --- a/packages/enclave-contracts/artifacts/contracts/registry/NaiveRegistryFilter.sol/NaiveRegistryFilter.json +++ b/packages/enclave-contracts/artifacts/contracts/registry/NaiveRegistryFilter.sol/NaiveRegistryFilter.json @@ -1,5 +1,5 @@ { - "_format": "hh-sol-artifact-1", + "_format": "hh3-artifact-1", "contractName": "NaiveRegistryFilter", "sourceName": "contracts/registry/NaiveRegistryFilter.sol", "abi": [ @@ -299,8 +299,11 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161105538038061105583398101604081905261002f91610326565b6100398282610040565b5050610359565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b031660008115801561008a5750825b90506000826001600160401b031660011480156100a65750303b155b9050811580156100b4575080155b156100d25760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831561010057845460ff60401b1916680100000000000000001785555b6101093361018c565b610112866101a0565b600080516020611035833981519152546001600160a01b0388811691161461013d5761013d876101ca565b831561018357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b61019461020a565b61019d8161025a565b50565b6101a8610262565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6101d2610262565b6001600160a01b03811661020157604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61019d816102ab565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661025857604051631afcd79f60e31b815260040160405180910390fd5b565b6101d261020a565b33610282600080516020611035833981519152546001600160a01b031690565b6001600160a01b0316146102585760405163118cdaa760e01b81523360048201526024016101f8565b60008051602061103583398151915280546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b80516001600160a01b038116811461032157600080fd5b919050565b6000806040838503121561033957600080fd5b6103428361030a565b91506103506020840161030a565b90509250929050565b610ccd806103686000396000f3fe608060405234801561001057600080fd5b50600436106100bd5760003560e01c80637b10399911610076578063a91ee0dc1161005b578063a91ee0dc14610199578063f2fde38b146101ac578063f5e820fd146101bf57600080fd5b80637b1039991461013e5780638da5cb5b1461016957600080fd5b80632b20a4f6116100a75780632b20a4f614610100578063485cc95514610123578063715018a61461013657600080fd5b806218449a146100c257806329f73b9c146100eb575b600080fd5b6100d56100d03660046108fc565b6101f0565b6040516100e29190610915565b60405180910390f35b6100fe6100f9366004610a87565b6102df565b005b61011361010e366004610b71565b6103c7565b60405190151581526020016100e2565b6100fe610131366004610ba4565b61045a565b6100fe6105c5565b600054610151906001600160a01b031681565b6040516001600160a01b0390911681526020016100e2565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610151565b6100fe6101a7366004610bd7565b6105d9565b6100fe6101ba366004610bd7565b610610565b6101e26101cd3660046108fc565b60016020526000908152604090206002015481565b6040519081526020016100e2565b6101f8610793565b6000828152600160209081526040918290208251815460809381028201840190945260608101848152909391928492849184018282801561026257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610244575b50505091835250506040805180820191829052602090920191906001840190600290826000855b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411610289579050505050505081526020016002820154815250509050919050565b6102e7610653565b60008381526001602052604090206002810154156103185760405163632a22bb60e01b815260040160405180910390fd5b825161032a90829060208601906107ba565b50815160208084019190912060028301556000546040516001600160a01b039091169163d9bbec9591879161036191889101610bf9565b604051602081830303815290604052856040518463ffffffff1660e01b815260040161038f93929190610c8b565b600060405180830381600087803b1580156103a957600080fd5b505af11580156103bd573d6000803e3d6000fd5b5050505050505050565b600080546001600160a01b031633146103f3576040516310f5403960e31b815260040160405180910390fd5b60008381526001602081905260409091200154640100000000900463ffffffff1615610432576040516334c2a65d60e11b815260040160405180910390fd5b6000838152600160208190526040909120610450910183600261082c565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156104a55750825b905060008267ffffffffffffffff1660011480156104c25750303b155b9050811580156104d0575080155b156104ee5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561052257845468ff00000000000000001916680100000000000000001785555b61052b336106ae565b610534866105d9565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b038881169116146105715761057187610610565b83156105bc57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105cd610653565b6105d760006106bf565b565b6105e1610653565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b610618610653565b6001600160a01b03811661064757604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610650816106bf565b50565b336106857f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105d75760405163118cdaa760e01b815233600482015260240161063e565b6106b661073d565b6106508161078b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166105d757604051631afcd79f60e31b815260040160405180910390fd5b61061861073d565b6040518060600160405280606081526020016107ad6108c9565b8152600060209091015290565b82805482825590600052602060002090810192821561081c579160200282015b8281111561081c578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039091161782556020909201916001909101906107da565b506108289291506108e7565b5090565b60018301918390821561081c5791602002820160005b8382111561088c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302610842565b80156108bc5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261088c565b50506108289291506108e7565b60405180604001604052806002906020820280368337509192915050565b5b8082111561082857600081556001016108e8565b60006020828403121561090e57600080fd5b5035919050565b60208082528251608083830152805160a084018190526000929190910190829060c08501905b80831015610967576001600160a01b03845116825260208201915060208401935060018301925061093b565b506020860151925060408501915060005b600281101561099d57835163ffffffff16835260209384019390920191600101610978565b506040860151608086015280935050505092915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109f3576109f36109b4565b604052919050565b80356001600160a01b0381168114610a1257600080fd5b919050565b600082601f830112610a2857600080fd5b813567ffffffffffffffff811115610a4257610a426109b4565b610a55601f8201601f19166020016109ca565b818152846020838601011115610a6a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610a9c57600080fd5b83359250602084013567ffffffffffffffff811115610aba57600080fd5b8401601f81018613610acb57600080fd5b803567ffffffffffffffff811115610ae557610ae56109b4565b8060051b610af5602082016109ca565b91825260208184018101929081019089841115610b1157600080fd5b6020850194505b83851015610b3a57610b29856109fb565b825260209485019490910190610b18565b95505050506040850135905067ffffffffffffffff811115610b5b57600080fd5b610b6786828701610a17565b9150509250925092565b60008060608385031215610b8457600080fd5b8235915060608301841015610b9857600080fd5b50926020919091019150565b60008060408385031215610bb757600080fd5b610bc0836109fb565b9150610bce602084016109fb565b90509250929050565b600060208284031215610be957600080fd5b610bf2826109fb565b9392505050565b602080825282518282018190526000918401906040840190835b81811015610c3a5783516001600160a01b0316835260209384019390920191600101610c13565b509095945050505050565b6000815180845260005b81811015610c6b57602081850181015186830182015201610c4f565b506000602082860101526020601f19601f83011685010191505092915050565b838152606060208201526000610ca46060830185610c45565b8281036040840152610cb68185610c45565b969550505050505056fea164736f6c634300081b000a9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100bd5760003560e01c80637b10399911610076578063a91ee0dc1161005b578063a91ee0dc14610199578063f2fde38b146101ac578063f5e820fd146101bf57600080fd5b80637b1039991461013e5780638da5cb5b1461016957600080fd5b80632b20a4f6116100a75780632b20a4f614610100578063485cc95514610123578063715018a61461013657600080fd5b806218449a146100c257806329f73b9c146100eb575b600080fd5b6100d56100d03660046108fc565b6101f0565b6040516100e29190610915565b60405180910390f35b6100fe6100f9366004610a87565b6102df565b005b61011361010e366004610b71565b6103c7565b60405190151581526020016100e2565b6100fe610131366004610ba4565b61045a565b6100fe6105c5565b600054610151906001600160a01b031681565b6040516001600160a01b0390911681526020016100e2565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610151565b6100fe6101a7366004610bd7565b6105d9565b6100fe6101ba366004610bd7565b610610565b6101e26101cd3660046108fc565b60016020526000908152604090206002015481565b6040519081526020016100e2565b6101f8610793565b6000828152600160209081526040918290208251815460809381028201840190945260608101848152909391928492849184018282801561026257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610244575b50505091835250506040805180820191829052602090920191906001840190600290826000855b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411610289579050505050505081526020016002820154815250509050919050565b6102e7610653565b60008381526001602052604090206002810154156103185760405163632a22bb60e01b815260040160405180910390fd5b825161032a90829060208601906107ba565b50815160208084019190912060028301556000546040516001600160a01b039091169163d9bbec9591879161036191889101610bf9565b604051602081830303815290604052856040518463ffffffff1660e01b815260040161038f93929190610c8b565b600060405180830381600087803b1580156103a957600080fd5b505af11580156103bd573d6000803e3d6000fd5b5050505050505050565b600080546001600160a01b031633146103f3576040516310f5403960e31b815260040160405180910390fd5b60008381526001602081905260409091200154640100000000900463ffffffff1615610432576040516334c2a65d60e11b815260040160405180910390fd5b6000838152600160208190526040909120610450910183600261082c565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156104a55750825b905060008267ffffffffffffffff1660011480156104c25750303b155b9050811580156104d0575080155b156104ee5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561052257845468ff00000000000000001916680100000000000000001785555b61052b336106ae565b610534866105d9565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b038881169116146105715761057187610610565b83156105bc57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105cd610653565b6105d760006106bf565b565b6105e1610653565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b610618610653565b6001600160a01b03811661064757604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610650816106bf565b50565b336106857f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105d75760405163118cdaa760e01b815233600482015260240161063e565b6106b661073d565b6106508161078b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166105d757604051631afcd79f60e31b815260040160405180910390fd5b61061861073d565b6040518060600160405280606081526020016107ad6108c9565b8152600060209091015290565b82805482825590600052602060002090810192821561081c579160200282015b8281111561081c578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039091161782556020909201916001909101906107da565b506108289291506108e7565b5090565b60018301918390821561081c5791602002820160005b8382111561088c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302610842565b80156108bc5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261088c565b50506108289291506108e7565b60405180604001604052806002906020820280368337509192915050565b5b8082111561082857600081556001016108e8565b60006020828403121561090e57600080fd5b5035919050565b60208082528251608083830152805160a084018190526000929190910190829060c08501905b80831015610967576001600160a01b03845116825260208201915060208401935060018301925061093b565b506020860151925060408501915060005b600281101561099d57835163ffffffff16835260209384019390920191600101610978565b506040860151608086015280935050505092915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109f3576109f36109b4565b604052919050565b80356001600160a01b0381168114610a1257600080fd5b919050565b600082601f830112610a2857600080fd5b813567ffffffffffffffff811115610a4257610a426109b4565b610a55601f8201601f19166020016109ca565b818152846020838601011115610a6a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610a9c57600080fd5b83359250602084013567ffffffffffffffff811115610aba57600080fd5b8401601f81018613610acb57600080fd5b803567ffffffffffffffff811115610ae557610ae56109b4565b8060051b610af5602082016109ca565b91825260208184018101929081019089841115610b1157600080fd5b6020850194505b83851015610b3a57610b29856109fb565b825260209485019490910190610b18565b95505050506040850135905067ffffffffffffffff811115610b5b57600080fd5b610b6786828701610a17565b9150509250925092565b60008060608385031215610b8457600080fd5b8235915060608301841015610b9857600080fd5b50926020919091019150565b60008060408385031215610bb757600080fd5b610bc0836109fb565b9150610bce602084016109fb565b90509250929050565b600060208284031215610be957600080fd5b610bf2826109fb565b9392505050565b602080825282518282018190526000918401906040840190835b81811015610c3a5783516001600160a01b0316835260209384019390920191600101610c13565b509095945050505050565b6000815180845260005b81811015610c6b57602081850181015186830182015201610c4f565b506000602082860101526020601f19601f83011685010191505092915050565b838152606060208201526000610ca46060830185610c45565b8281036040840152610cb68185610c45565b969550505050505056fea164736f6c634300081b000a", + "bytecode": "0x608060405234801561000f575f5ffd5b5060405161101638038061101683398101604081905261002e916102f6565b610038828261003f565b5050610327565b5f516020610ff65f395f51905f52805468010000000000000000810460ff1615906001600160401b03165f811580156100755750825b90505f826001600160401b031660011480156100905750303b155b90508115801561009e575080155b156100bc5760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b031916600117855583156100ea57845460ff60401b1916680100000000000000001785555b6100f333610175565b6100fc86610189565b5f516020610fd65f395f51905f52546001600160a01b0388811691161461012657610126876101b2565b831561016c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b61017d6101f1565b6101868161022e565b50565b610191610236565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b6101ba610236565b6001600160a01b0381166101e857604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101868161027e565b5f516020610ff65f395f51905f525468010000000000000000900460ff1661022c57604051631afcd79f60e31b815260040160405180910390fd5b565b6101ba6101f1565b336102555f516020610fd65f395f51905f52546001600160a01b031690565b6001600160a01b03161461022c5760405163118cdaa760e01b81523360048201526024016101df565b5f516020610fd65f395f51905f5280546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b80516001600160a01b03811681146102f1575f5ffd5b919050565b5f5f60408385031215610307575f5ffd5b610310836102db565b915061031e602084016102db565b90509250929050565b610ca2806103345f395ff3fe608060405234801561000f575f5ffd5b50600436106100b8575f3560e01c80637b10399911610072578063a91ee0dc11610058578063a91ee0dc14610192578063f2fde38b146101a5578063f5e820fd146101b8575f5ffd5b80637b103999146101385780638da5cb5b14610162575f5ffd5b80632b20a4f6116100a25780632b20a4f6146100fa578063485cc9551461011d578063715018a614610130575f5ffd5b806218449a146100bc57806329f73b9c146100e5575b5f5ffd5b6100cf6100ca3660046108db565b6101e8565b6040516100dc91906108f2565b60405180910390f35b6100f86100f3366004610a5b565b6102d3565b005b61010d610108366004610b3e565b6103b4565b60405190151581526020016100dc565b6100f861012b366004610b6e565b610444565b6100f86105ad565b5f5461014a906001600160a01b031681565b6040516001600160a01b0390911681526020016100dc565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661014a565b6100f86101a0366004610b9f565b6105c0565b6100f86101b3366004610b9f565b6105f6565b6101da6101c63660046108db565b60016020525f908152604090206002015481565b6040519081526020016100dc565b6101f0610777565b5f828152600160209081526040918290208251815460809381028201840190945260608101848152909391928492849184018282801561025757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610239575b50505091835250506040805180820191829052602090920191906001840190600290825f855b82829054906101000a900463ffffffff1663ffffffff168152602001906004019060208260030104928301926001038202915080841161027d579050505050505081526020016002820154815250509050919050565b6102db610638565b5f83815260016020526040902060028101541561030b5760405163632a22bb60e01b815260040160405180910390fd5b825161031d908290602086019061079d565b50815160208084019190912060028301555f546040516001600160a01b039091169163d9bbec9591879161035391889101610bbf565b604051602081830303815290604052856040518463ffffffff1660e01b815260040161038193929190610c38565b5f604051808303815f87803b158015610398575f5ffd5b505af11580156103aa573d5f5f3e3d5ffd5b5050505050505050565b5f80546001600160a01b031633146103df576040516310f5403960e31b815260040160405180910390fd5b5f8381526001602081905260409091200154640100000000900463ffffffff161561041d576040516334c2a65d60e11b815260040160405180910390fd5b5f83815260016020819052604090912061043a910183600261080d565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f8115801561048e5750825b90505f8267ffffffffffffffff1660011480156104aa5750303b155b9050811580156104b8575080155b156104d65760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561050a57845468ff00000000000000001916680100000000000000001785555b61051333610693565b61051c866105c0565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0388811691161461055957610559876105f6565b83156105a457845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105b5610638565b6105be5f6106a4565b565b6105c8610638565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6105fe610638565b6001600160a01b03811661062c57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b610635816106a4565b50565b3361066a7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105be5760405163118cdaa760e01b8152336004820152602401610623565b61069b610721565b6106358161076f565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166105be57604051631afcd79f60e31b815260040160405180910390fd5b6105fe610721565b6040518060600160405280606081526020016107916108a9565b81526020015f81525090565b828054828255905f5260205f209081019282156107fd579160200282015b828111156107fd578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039091161782556020909201916001909101906107bb565b506108099291506108c7565b5090565b6001830191839082156107fd579160200282015f5b8382111561086c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302610822565b801561089c5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261086c565b50506108099291506108c7565b60405180604001604052806002906020820280368337509192915050565b5b80821115610809575f81556001016108c8565b5f602082840312156108eb575f5ffd5b5035919050565b60208082528251608083830152805160a084018190525f929190910190829060c08501905b80831015610943576001600160a01b038451168252602082019150602084019350600183019250610917565b50602086015192506040850191505f5b600281101561097857835163ffffffff16835260209384019390920191600101610953565b506040860151608086015280935050505092915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098f565b604052919050565b80356001600160a01b03811681146109ea575f5ffd5b919050565b5f82601f8301126109fe575f5ffd5b813567ffffffffffffffff811115610a1857610a1861098f565b610a2b601f8201601f19166020016109a3565b818152846020838601011115610a3f575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f60608486031215610a6d575f5ffd5b83359250602084013567ffffffffffffffff811115610a8a575f5ffd5b8401601f81018613610a9a575f5ffd5b803567ffffffffffffffff811115610ab457610ab461098f565b8060051b610ac4602082016109a3565b91825260208184018101929081019089841115610adf575f5ffd5b6020850194505b83851015610b0857610af7856109d4565b825260209485019490910190610ae6565b95505050506040850135905067ffffffffffffffff811115610b28575f5ffd5b610b34868287016109ef565b9150509250925092565b5f5f60608385031215610b4f575f5ffd5b8235915060608301841015610b62575f5ffd5b50926020919091019150565b5f5f60408385031215610b7f575f5ffd5b610b88836109d4565b9150610b96602084016109d4565b90509250929050565b5f60208284031215610baf575f5ffd5b610bb8826109d4565b9392505050565b602080825282518282018190525f918401906040840190835b81811015610bff5783516001600160a01b0316835260209384019390920191600101610bd8565b509095945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b838152606060208201525f610c506060830185610c0a565b8281036040840152610c628185610c0a565b969550505050505056fea264697066735822122068fdfe7cc2dabe1489d6e078852b41896b5861e2751c635ebac8bafdd7de81bf64736f6c634300081b00339016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100b8575f3560e01c80637b10399911610072578063a91ee0dc11610058578063a91ee0dc14610192578063f2fde38b146101a5578063f5e820fd146101b8575f5ffd5b80637b103999146101385780638da5cb5b14610162575f5ffd5b80632b20a4f6116100a25780632b20a4f6146100fa578063485cc9551461011d578063715018a614610130575f5ffd5b806218449a146100bc57806329f73b9c146100e5575b5f5ffd5b6100cf6100ca3660046108db565b6101e8565b6040516100dc91906108f2565b60405180910390f35b6100f86100f3366004610a5b565b6102d3565b005b61010d610108366004610b3e565b6103b4565b60405190151581526020016100dc565b6100f861012b366004610b6e565b610444565b6100f86105ad565b5f5461014a906001600160a01b031681565b6040516001600160a01b0390911681526020016100dc565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661014a565b6100f86101a0366004610b9f565b6105c0565b6100f86101b3366004610b9f565b6105f6565b6101da6101c63660046108db565b60016020525f908152604090206002015481565b6040519081526020016100dc565b6101f0610777565b5f828152600160209081526040918290208251815460809381028201840190945260608101848152909391928492849184018282801561025757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610239575b50505091835250506040805180820191829052602090920191906001840190600290825f855b82829054906101000a900463ffffffff1663ffffffff168152602001906004019060208260030104928301926001038202915080841161027d579050505050505081526020016002820154815250509050919050565b6102db610638565b5f83815260016020526040902060028101541561030b5760405163632a22bb60e01b815260040160405180910390fd5b825161031d908290602086019061079d565b50815160208084019190912060028301555f546040516001600160a01b039091169163d9bbec9591879161035391889101610bbf565b604051602081830303815290604052856040518463ffffffff1660e01b815260040161038193929190610c38565b5f604051808303815f87803b158015610398575f5ffd5b505af11580156103aa573d5f5f3e3d5ffd5b5050505050505050565b5f80546001600160a01b031633146103df576040516310f5403960e31b815260040160405180910390fd5b5f8381526001602081905260409091200154640100000000900463ffffffff161561041d576040516334c2a65d60e11b815260040160405180910390fd5b5f83815260016020819052604090912061043a910183600261080d565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f8115801561048e5750825b90505f8267ffffffffffffffff1660011480156104aa5750303b155b9050811580156104b8575080155b156104d65760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561050a57845468ff00000000000000001916680100000000000000001785555b61051333610693565b61051c866105c0565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0388811691161461055957610559876105f6565b83156105a457845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105b5610638565b6105be5f6106a4565b565b6105c8610638565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6105fe610638565b6001600160a01b03811661062c57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b610635816106a4565b50565b3361066a7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146105be5760405163118cdaa760e01b8152336004820152602401610623565b61069b610721565b6106358161076f565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166105be57604051631afcd79f60e31b815260040160405180910390fd5b6105fe610721565b6040518060600160405280606081526020016107916108a9565b81526020015f81525090565b828054828255905f5260205f209081019282156107fd579160200282015b828111156107fd578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039091161782556020909201916001909101906107bb565b506108099291506108c7565b5090565b6001830191839082156107fd579160200282015f5b8382111561086c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302610822565b801561089c5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261086c565b50506108099291506108c7565b60405180604001604052806002906020820280368337509192915050565b5b80821115610809575f81556001016108c8565b5f602082840312156108eb575f5ffd5b5035919050565b60208082528251608083830152805160a084018190525f929190910190829060c08501905b80831015610943576001600160a01b038451168252602082019150602084019350600183019250610917565b50602086015192506040850191505f5b600281101561097857835163ffffffff16835260209384019390920191600101610953565b506040860151608086015280935050505092915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098f565b604052919050565b80356001600160a01b03811681146109ea575f5ffd5b919050565b5f82601f8301126109fe575f5ffd5b813567ffffffffffffffff811115610a1857610a1861098f565b610a2b601f8201601f19166020016109a3565b818152846020838601011115610a3f575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f60608486031215610a6d575f5ffd5b83359250602084013567ffffffffffffffff811115610a8a575f5ffd5b8401601f81018613610a9a575f5ffd5b803567ffffffffffffffff811115610ab457610ab461098f565b8060051b610ac4602082016109a3565b91825260208184018101929081019089841115610adf575f5ffd5b6020850194505b83851015610b0857610af7856109d4565b825260209485019490910190610ae6565b95505050506040850135905067ffffffffffffffff811115610b28575f5ffd5b610b34868287016109ef565b9150509250925092565b5f5f60608385031215610b4f575f5ffd5b8235915060608301841015610b62575f5ffd5b50926020919091019150565b5f5f60408385031215610b7f575f5ffd5b610b88836109d4565b9150610b96602084016109d4565b90509250929050565b5f60208284031215610baf575f5ffd5b610bb8826109d4565b9392505050565b602080825282518282018190525f918401906040840190835b81811015610bff5783516001600160a01b0316835260209384019390920191600101610bd8565b509095945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b838152606060208201525f610c506060830185610c0a565b8281036040840152610c628185610c0a565b969550505050505056fea264697066735822122068fdfe7cc2dabe1489d6e078852b41896b5861e2751c635ebac8bafdd7de81bf64736f6c634300081b0033", "linkReferences": {}, - "deployedLinkReferences": {} -} + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/contracts/registry/NaiveRegistryFilter.sol", + "buildInfoId": "solc-0_8_27-8287ebf5be05227965814498ddef24fc9009e2f0" +} \ No newline at end of file diff --git a/packages/enclave-contracts/contracts/Enclave.sol b/packages/enclave-contracts/contracts/Enclave.sol index 90307b7800..3dd8e1d3de 100644 --- a/packages/enclave-contracts/contracts/Enclave.sol +++ b/packages/enclave-contracts/contracts/Enclave.sol @@ -170,6 +170,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { IDecryptionVerifier decryptionVerifier = decryptionVerifiers[ encryptionSchemeId ]; + require( decryptionVerifiers[encryptionSchemeId] != IDecryptionVerifier(address(0)), diff --git a/packages/enclave-contracts/contracts/interfaces/IEnclave.sol b/packages/enclave-contracts/contracts/interfaces/IEnclave.sol index f578c6bbe4..7f3feeb8ff 100644 --- a/packages/enclave-contracts/contracts/interfaces/IEnclave.sol +++ b/packages/enclave-contracts/contracts/interfaces/IEnclave.sol @@ -121,7 +121,7 @@ interface IEnclave { /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @dev This function MUST emit the E3Requested event. - /// @param requestParams The parameters for the request. + /// @param requestParams The parameters for the E3 request. /// @return e3Id ID of the E3. /// @return e3 The E3 struct. function request( diff --git a/packages/enclave-contracts/contracts/registry/NaiveRegistryFilter.sol b/packages/enclave-contracts/contracts/registry/NaiveRegistryFilter.sol index c2fc666871..a5b18a4f2f 100644 --- a/packages/enclave-contracts/contracts/registry/NaiveRegistryFilter.sol +++ b/packages/enclave-contracts/contracts/registry/NaiveRegistryFilter.sol @@ -101,6 +101,7 @@ contract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable { require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished()); committee.nodes = nodes; committee.publicKey = keccak256(publicKey); + ICiphernodeRegistry(registry).publishCommittee( e3Id, abi.encode(nodes), diff --git a/packages/enclave-contracts/contracts/test/MockE3Program.sol b/packages/enclave-contracts/contracts/test/MockE3Program.sol index b684cc45b3..b7cb563188 100644 --- a/packages/enclave-contracts/contracts/test/MockE3Program.sol +++ b/packages/enclave-contracts/contracts/test/MockE3Program.sol @@ -36,8 +36,6 @@ contract MockE3Program is IE3Program { ); require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized()); - paramsHashes[e3Id] = keccak256(e3ProgramParams); - paramsHashes[e3Id] = keccak256(e3ProgramParams); return (ENCRYPTION_SCHEME_ID, inputValidator); } diff --git a/packages/enclave-contracts/deploy/enclave.ts b/packages/enclave-contracts/deploy/enclave.ts deleted file mode 100644 index b86d986add..0000000000 --- a/packages/enclave-contracts/deploy/enclave.ts +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import "@nomicfoundation/hardhat-ethers"; -import { ethers } from "ethers"; -import "hardhat-deploy"; -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { PoseidonT3, proxy } from "poseidon-solidity"; - -const THIRTY_DAYS_IN_SECONDS = 60 * 60 * 24 * 30; -const addressOne = "0x0000000000000000000000000000000000000001"; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployer } = await hre.getNamedAccounts(); - const { deploy } = hre.deployments; - - if (!deployer) { - throw new Error("Deployer not found from getNamedAccounts()"); - } - - // First check if the proxy exists - if ((await hre.ethers.provider.getCode(proxy.address)) === "0x") { - // probably on the hardhat network - // fund the keyless account - const [sender] = await hre.ethers.getSigners(); - await sender!.sendTransaction({ - to: proxy.from, - value: proxy.gas, - }); - - // then send the presigned transaction deploying the proxy - await hre.ethers.provider.broadcastTransaction(proxy.tx); - console.log(`Proxy deployed to: ${proxy.address}`); - } - - // Then deploy the hasher, if needed - if ((await hre.ethers.provider.getCode(PoseidonT3.address)) === "0x") { - const [sender] = await hre.ethers.getSigners(); - await sender!.sendTransaction({ - to: proxy.address, - data: PoseidonT3.data, - }); - - console.log(`PoseidonT3 deployed to: ${PoseidonT3.address}`); - } - - // Deploy Enclave contract - const polynomial_degree = ethers.toBigInt(2048); - const plaintext_modulus = ethers.toBigInt(1032193); - const moduli = [ethers.toBigInt("18014398492704769")]; - - // Encode just the struct (NOT the function selector) - const encoded = ethers.AbiCoder.defaultAbiCoder().encode( - ["uint256", "uint256", "uint256[]"], - [polynomial_degree, plaintext_modulus, moduli], - ); - - const enclave = await deploy("Enclave", { - from: deployer, - args: [deployer, addressOne, THIRTY_DAYS_IN_SECONDS, [encoded]], - log: true, - libraries: { - PoseidonT3: PoseidonT3.address, - }, - }); - - console.log(`Enclave contract: `, enclave.address); - - // Deploy CiphernodeRegistryOwnable contract - - const cypherNodeRegistry = await deploy("CiphernodeRegistryOwnable", { - from: deployer, - args: [deployer, enclave.address], - log: true, - libraries: { - PoseidonT3: PoseidonT3.address, - }, - }); - - console.log( - `CiphernodeRegistryOwnable contract: `, - cypherNodeRegistry.address, - ); - - // Deploy NaiveRegistryFilter contract - - const naiveRegistryFilter = await deploy("NaiveRegistryFilter", { - from: deployer, - args: [deployer, cypherNodeRegistry.address], - log: true, - }); - - console.log(`NaiveRegistryFilter contract: `, naiveRegistryFilter.address); - - // set registry in enclave - const enclaveArtifact = await hre.deployments.getArtifact("Enclave"); - const enclaveContract = new hre.ethers.Contract( - enclave.address, - enclaveArtifact.abi, - await hre.ethers.getSigner(deployer), - ); - - const registryAddress = await enclaveContract.ciphernodeRegistry!(); - - if (registryAddress === cypherNodeRegistry.address) { - console.log(`Enclave contract already has registry`); - return; - } - - const result = await enclaveContract.setCiphernodeRegistry!( - cypherNodeRegistry.address, - ); - await result.wait(); - console.log(`Enclave contract updated with registry`); -}; -export default func; -func.tags = ["enclave"]; diff --git a/packages/enclave-contracts/deploy/mocks.ts b/packages/enclave-contracts/deploy/mocks.ts deleted file mode 100644 index acdb37d860..0000000000 --- a/packages/enclave-contracts/deploy/mocks.ts +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import "@nomicfoundation/hardhat-ethers"; -import "hardhat-deploy"; -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployer } = await hre.getNamedAccounts(); - const { deploy } = hre.deployments; - if (!deployer) - throw new Error("Deployer not returned from getNamedAddresses()"); - - const computeProvider = await deploy("MockComputeProvider", { - from: deployer, - args: [], - log: true, - }); - - const mockDecryptionVerifier = await deploy("MockDecryptionVerifier", { - from: deployer, - args: [], - log: true, - }); - - const mockInputValidator = await deploy("MockInputValidator", { - from: deployer, - args: [], - log: true, - }); - - const mockE3Program = await deploy("MockE3Program", { - from: deployer, - args: [mockInputValidator.address], - log: true, - }); - - console.log(` -MockDeployments: ----------------------------------------------------------------------- -MockComputeProvider:${computeProvider.address} -MockDecryptionVerifier:${mockDecryptionVerifier.address} -MockInputValidator:${mockInputValidator.address} -MockE3Program:${mockE3Program.address} -`); - - // Set up MockDecryptionVerifier in Enclave contract - const enclaveDeployment = await hre.deployments.get("Enclave"); - const enclaveArtifact = await hre.deployments.getArtifact("Enclave"); - const enclaveContract = new hre.ethers.Contract( - enclaveDeployment.address, - enclaveArtifact.abi, - await hre.ethers.getSigner(deployer), - ); - - const encryptionSchemeId = hre.ethers.keccak256( - hre.ethers.toUtf8Bytes("fhe.rs:BFV"), - ); - - try { - const tx = await enclaveContract.setDecryptionVerifier!( - encryptionSchemeId, - mockDecryptionVerifier.address, - ); - await tx.wait(); - console.log(`Successfully set MockDecryptionVerifier in Enclave contract`); - } catch (error) { - console.error("Error setting MockDecryptionVerifier:", error); - process.exit(1); - } -}; -export default func; -func.tags = ["mocks"]; diff --git a/packages/enclave-contracts/deployed_contracts.json b/packages/enclave-contracts/deployed_contracts.json new file mode 100644 index 0000000000..906896bb54 --- /dev/null +++ b/packages/enclave-contracts/deployed_contracts.json @@ -0,0 +1,30 @@ +{ + "sepolia": { + "Enclave": { + "constructorArgs": { + "params": "0x000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000fc00100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000003fffffff000001", + "owner": "0x4f1f3a157073A35515C4fC4A8af2F1Af088f0676", + "maxDuration": "2592000", + "registry": "0x0000000000000000000000000000000000000001" + }, + "blockNumber": 9181738, + "address": "0xD43c70A343E631475d8470d0403e0c4b43c76927" + }, + "CiphernodeRegistry": { + "constructorArgs": { + "enclaveAddress": "0xD43c70A343E631475d8470d0403e0c4b43c76927", + "owner": "0x4f1f3a157073A35515C4fC4A8af2F1Af088f0676" + }, + "blockNumber": 9181748, + "address": "0x5ABDfCbA0366ABF2893D3f2465F4C97908488A6d" + }, + "NaiveRegistryFilter": { + "constructorArgs": { + "ciphernodeRegistryAddress": "0x5ABDfCbA0366ABF2893D3f2465F4C97908488A6d", + "owner": "0x4f1f3a157073A35515C4fC4A8af2F1Af088f0676" + }, + "blockNumber": 9181753, + "address": "0x58708A1bf1AEdf8e75755FDa1882F8dc46985009" + } + } +} diff --git a/packages/enclave-contracts/deployments/sepolia/.chainId b/packages/enclave-contracts/deployments/sepolia/.chainId deleted file mode 100644 index bd8d1cd44c..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/.chainId +++ /dev/null @@ -1 +0,0 @@ -11155111 \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/CiphernodeRegistryOwnable.json b/packages/enclave-contracts/deployments/sepolia/CiphernodeRegistryOwnable.json deleted file mode 100644 index 857bf3339a..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/CiphernodeRegistryOwnable.json +++ /dev/null @@ -1,961 +0,0 @@ -{ - "address": "0x4A6701c770c53584b7d781ccC0267152d128bd4E", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_enclave", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - } - ], - "name": "CiphernodeNotEnabled", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeAlreadyPublished", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeAlreadyRequested", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeNotPublished", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "LeafAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "LeafCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "LeafDoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "LeafGreaterThanSnarkScalarField", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyEnclave", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFilter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "WrongSiblingNodes", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "node", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "numNodes", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "size", - "type": "uint256" - } - ], - "name": "CiphernodeAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "node", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "numNodes", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "size", - "type": "uint256" - } - ], - "name": "CiphernodeRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - } - ], - "name": "CommitteePublished", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "filter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - } - ], - "name": "CommitteeRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "enclave", - "type": "address" - } - ], - "name": "EnclaveSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - } - ], - "name": "addCiphernode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "ciphernodes", - "outputs": [ - { - "internalType": "uint256", - "name": "size", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depth", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "committeePublicKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "publicKeyHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "enclave", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "filters", - "outputs": [ - { - "internalType": "contract IRegistryFilter", - "name": "filter", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "getFilter", - "outputs": [ - { - "internalType": "contract IRegistryFilter", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_enclave", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - } - ], - "name": "isCiphernodeEligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - } - ], - "name": "isEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numCiphernodes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "publicKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "publicKeyHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - } - ], - "name": "publishCommittee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "siblingNodes", - "type": "uint256[]" - } - ], - "name": "removeCiphernode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "filter", - "type": "address" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - } - ], - "name": "requestCommittee", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "root", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "rootAt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "roots", - "outputs": [ - { - "internalType": "uint256", - "name": "root", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_enclave", - "type": "address" - } - ], - "name": "setEnclave", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "treeSize", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x146099bfb03e2f479887283ec82df6c4c8d11384eebfb22d640e07c50f957dd7", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0x4A6701c770c53584b7d781ccC0267152d128bd4E", - "transactionIndex": 136, - "gasUsed": "1212915", - "logsBloom": "0x00000000000000000001000000000002000000000000000000800000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000001000000000000000040000000000020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000004080000000000000000000000000000000000000000000010000000000000000000040000000000004000000000020000000000000020000000002000000000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x483fe0f85cc08b523999f1e6edb7c182a737467d9289ca75f5074c445b152fd0", - "transactionHash": "0x146099bfb03e2f479887283ec82df6c4c8d11384eebfb22d640e07c50f957dd7", - "logs": [ - { - "transactionIndex": 136, - "blockNumber": 8360699, - "transactionHash": "0x146099bfb03e2f479887283ec82df6c4c8d11384eebfb22d640e07c50f957dd7", - "address": "0x4A6701c770c53584b7d781ccC0267152d128bd4E", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000008837e47c4bb520ade83aab761c3b60679443af1b" - ], - "data": "0x", - "logIndex": 163, - "blockHash": "0x483fe0f85cc08b523999f1e6edb7c182a737467d9289ca75f5074c445b152fd0" - }, - { - "transactionIndex": 136, - "blockNumber": 8360699, - "transactionHash": "0x146099bfb03e2f479887283ec82df6c4c8d11384eebfb22d640e07c50f957dd7", - "address": "0x4A6701c770c53584b7d781ccC0267152d128bd4E", - "topics": [ - "0x2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9", - "0x0000000000000000000000006307a84b88f2641f197359a95bc6029bf33f54fb" - ], - "data": "0x", - "logIndex": 164, - "blockHash": "0x483fe0f85cc08b523999f1e6edb7c182a737467d9289ca75f5074c445b152fd0" - }, - { - "transactionIndex": 136, - "blockNumber": 8360699, - "transactionHash": "0x146099bfb03e2f479887283ec82df6c4c8d11384eebfb22d640e07c50f957dd7", - "address": "0x4A6701c770c53584b7d781ccC0267152d128bd4E", - "topics": [ - "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 165, - "blockHash": "0x483fe0f85cc08b523999f1e6edb7c182a737467d9289ca75f5074c445b152fd0" - } - ], - "blockNumber": 8360699, - "cumulativeGasUsed": "10145917", - "status": 1, - "byzantium": true - }, - "args": [ - "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "0x6307a84B88F2641f197359a95BC6029bF33f54fb" - ], - "numDeployments": 3, - "solcInputHash": "7505270e9ddb813a3809c10e5d95f372", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"CiphernodeNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeNotPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafGreaterThanSnarkScalarField\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyEnclave\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFilter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongSiblingNodes\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"numNodes\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"CiphernodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"numNodes\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"CiphernodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"CommitteePublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"CommitteeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"enclave\",\"type\":\"address\"}],\"name\":\"EnclaveSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"addCiphernode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ciphernodes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"depth\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"committeePublicKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"publicKeyHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"enclave\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"filters\",\"outputs\":[{\"internalType\":\"contract IRegistryFilter\",\"name\":\"filter\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"getFilter\",\"outputs\":[{\"internalType\":\"contract IRegistryFilter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"isCiphernodeEligible\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"isEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numCiphernodes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"publicKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"publicKeyHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"publishCommittee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"siblingNodes\",\"type\":\"uint256[]\"}],\"name\":\"removeCiphernode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"requestCommittee\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"root\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"rootAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"roots\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"name\":\"setEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treeSize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"CiphernodeAdded(address,uint256,uint256,uint256)\":{\"params\":{\"index\":\"Index of the ciphernode in the registry.\",\"node\":\"Address of the ciphernode.\",\"numNodes\":\"Number of ciphernodes in the registry.\",\"size\":\"Size of the registry.\"}},\"CiphernodeRemoved(address,uint256,uint256,uint256)\":{\"params\":{\"index\":\"Index of the ciphernode in the registry.\",\"node\":\"Address of the ciphernode.\",\"numNodes\":\"Number of ciphernodes in the registry.\",\"size\":\"Size of the registry.\"}},\"CommitteePublished(uint256,bytes)\":{\"params\":{\"e3Id\":\"ID of the E3 for which the committee was selected.\",\"publicKey\":\"Public key of the committee.\"}},\"CommitteeRequested(uint256,address,uint32[2])\":{\"params\":{\"e3Id\":\"ID of the E3 for which the committee was selected.\",\"filter\":\"Address of the contract that will coordinate committee selection.\",\"threshold\":\"The M/N threshold for the committee.\"}},\"EnclaveSet(address)\":{\"params\":{\"enclave\":\"Address of the enclave contract.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{\"committeePublicKey(uint256)\":{\"details\":\"This function MUST revert if no committee has been requested for the given E3.This function MUST revert if the committee has not yet published a public key.\",\"params\":{\"e3Id\":\"ID of the E3 for which to get the committee public key.\"},\"returns\":{\"publicKeyHash\":\"The hash of the public key of the given committee.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"requestCommittee(uint256,address,uint32[2])\":{\"details\":\"This function MUST revert when not called by the Enclave contract.\",\"params\":{\"e3Id\":\"ID of the E3 for which to select the committee.\",\"filter\":\"The address of the filter responsible for the committee selection process.\",\"threshold\":\"The M/N threshold for the committee.\"},\"returns\":{\"success\":\"True if committee selection was successfully initiated.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"CiphernodeAdded(address,uint256,uint256,uint256)\":{\"notice\":\"This event MUST be emitted when a ciphernode is added to the registry.\"},\"CiphernodeRemoved(address,uint256,uint256,uint256)\":{\"notice\":\"This event MUST be emitted when a ciphernode is removed from the registry.\"},\"CommitteePublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when a committee is selected for an E3.\"},\"CommitteeRequested(uint256,address,uint32[2])\":{\"notice\":\"This event MUST be emitted when a committee is selected for an E3.\"},\"EnclaveSet(address)\":{\"notice\":\"This event MUST be emitted when `enclave` is set.\"}},\"kind\":\"user\",\"methods\":{\"committeePublicKey(uint256)\":{\"notice\":\"This function should be called by the Enclave contract to get the public key of a committee.\"},\"requestCommittee(uint256,address,uint32[2])\":{\"notice\":\"Initiates the committee selection process for a specified E3.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/registry/CiphernodeRegistryOwnable.sol\":\"CiphernodeRegistryOwnable\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"@zk-kit/lean-imt.sol/Constants.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.4;\\n\\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\\n\",\"keccak256\":\"0xb1944a1d9f63069b2f22260935adb2d11546f82fbb7d12d853a90134a92f4b5b\",\"license\":\"UNLICENSED\"},\"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {PoseidonT3} from \\\"poseidon-solidity/PoseidonT3.sol\\\";\\nimport {SNARK_SCALAR_FIELD} from \\\"./Constants.sol\\\";\\n\\nstruct LeanIMTData {\\n // Tracks the current number of leaves in the tree.\\n uint256 size;\\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\\n uint256 depth;\\n // A mapping from each level of the tree to the node value of the last even position at that level.\\n // Used for efficient inserts, updates and root calculations.\\n mapping(uint256 => uint256) sideNodes;\\n // A mapping from leaf values to their respective indices in the tree.\\n // This facilitates checks for leaf existence and retrieval of leaf positions.\\n mapping(uint256 => uint256) leaves;\\n}\\n\\nerror WrongSiblingNodes();\\nerror LeafGreaterThanSnarkScalarField();\\nerror LeafCannotBeZero();\\nerror LeafAlreadyExists();\\nerror LeafDoesNotExist();\\n\\n/// @title Lean Incremental binary Merkle tree.\\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\\n/// it is updated based on the number of leaves in the tree. This approach\\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\\nlibrary InternalLeanIMT {\\n /// @dev Inserts a new leaf into the incremental merkle tree.\\n /// The function ensures that the leaf is valid according to the\\n /// constraints of the tree and then updates the tree's structure accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the new leaf to be inserted into the tree.\\n /// @return The new hash of the node after the leaf has been inserted.\\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\\n if (leaf >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (leaf == 0) {\\n revert LeafCannotBeZero();\\n } else if (_has(self, leaf)) {\\n revert LeafAlreadyExists();\\n }\\n\\n uint256 index = self.size;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n // A new insertion can increase a tree's depth by at most 1,\\n // and only if the number of leaves supported by the current\\n // depth is less than the number of leaves to be supported after insertion.\\n if (2 ** treeDepth < index + 1) {\\n ++treeDepth;\\n }\\n\\n self.depth = treeDepth;\\n\\n uint256 node = leaf;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n if ((index >> level) & 1 == 1) {\\n node = PoseidonT3.hash([self.sideNodes[level], node]);\\n } else {\\n self.sideNodes[level] = node;\\n }\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n self.size = ++index;\\n\\n self.sideNodes[treeDepth] = node;\\n self.leaves[leaf] = index;\\n\\n return node;\\n }\\n\\n /// @dev Inserts many leaves into the incremental merkle tree.\\n /// The function ensures that the leaves are valid according to the\\n /// constraints of the tree and then updates the tree's structure accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaves: The values of the new leaves to be inserted into the tree.\\n /// @return The root after the leaves have been inserted.\\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\\n // Cache tree size to optimize gas\\n uint256 treeSize = self.size;\\n\\n // Check that all the new values are correct to be added.\\n for (uint256 i = 0; i < leaves.length; ) {\\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (leaves[i] == 0) {\\n revert LeafCannotBeZero();\\n } else if (_has(self, leaves[i])) {\\n revert LeafAlreadyExists();\\n }\\n\\n self.leaves[leaves[i]] = treeSize + 1 + i;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Array to save the nodes that will be used to create the next level of the tree.\\n uint256[] memory currentLevelNewNodes;\\n\\n currentLevelNewNodes = leaves;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n // Calculate the depth of the tree after adding the new values.\\n // Unlike the 'insert' function, we need a while here as\\n // N insertions can increase the tree's depth more than once.\\n while (2 ** treeDepth < treeSize + leaves.length) {\\n ++treeDepth;\\n }\\n\\n self.depth = treeDepth;\\n\\n // First index to change in every level.\\n uint256 currentLevelStartIndex = treeSize;\\n\\n // Size of the level used to create the next level.\\n uint256 currentLevelSize = treeSize + leaves.length;\\n\\n // The index where changes begin at the next level.\\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\\n\\n // The size of the next level.\\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n // The number of nodes for the new level that will be created,\\n // only the new values, not the entire level.\\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\\n for (uint256 i = 0; i < numberOfNewNodes; ) {\\n uint256 leftNode;\\n\\n // Assign the left node using the saved path or the position in the array.\\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\\n leftNode = self.sideNodes[level];\\n } else {\\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\\n }\\n\\n uint256 rightNode;\\n\\n // Assign the right node if the value exists.\\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\\n }\\n\\n uint256 parentNode;\\n\\n // Assign the parent node.\\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\\n // it will be the leftNode.\\n if (rightNode != 0) {\\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\\n } else {\\n parentNode = leftNode;\\n }\\n\\n nextLevelNewNodes[i] = parentNode;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Update the `sideNodes` variable.\\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\\n // will be the value before the last one.\\n // If it is even and there is only one element, there is no need to save anything because\\n // the correct value for this level was already saved before.\\n if (currentLevelSize & 1 == 1) {\\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\\n } else if (currentLevelNewNodes.length > 1) {\\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\\n }\\n\\n currentLevelStartIndex = nextLevelStartIndex;\\n\\n // Calculate the next level startIndex value.\\n // It is the position of the parent node which is pos/2.\\n nextLevelStartIndex >>= 1;\\n\\n // Update the next array that will be used to calculate the next level.\\n currentLevelNewNodes = nextLevelNewNodes;\\n\\n currentLevelSize = nextLevelSize;\\n\\n // Calculate the size of the next level.\\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n // Update tree size\\n self.size = treeSize + leaves.length;\\n\\n // Update tree root\\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\\n\\n return currentLevelNewNodes[0];\\n }\\n\\n /// @dev Updates the value of an existing leaf and recalculates hashes\\n /// to maintain tree integrity.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param oldLeaf: The value of the leaf that is to be updated.\\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\\n /// @return The new hash of the updated node after the leaf has been updated.\\n function _update(\\n LeanIMTData storage self,\\n uint256 oldLeaf,\\n uint256 newLeaf,\\n uint256[] calldata siblingNodes\\n ) internal returns (uint256) {\\n if (newLeaf >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (!_has(self, oldLeaf)) {\\n revert LeafDoesNotExist();\\n } else if (_has(self, newLeaf)) {\\n revert LeafAlreadyExists();\\n }\\n\\n uint256 index = _indexOf(self, oldLeaf);\\n uint256 node = newLeaf;\\n uint256 oldRoot = oldLeaf;\\n\\n uint256 lastIndex = self.size - 1;\\n uint256 i = 0;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n if ((index >> level) & 1 == 1) {\\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n }\\n\\n node = PoseidonT3.hash([siblingNodes[i], node]);\\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\\n\\n unchecked {\\n ++i;\\n }\\n } else {\\n if (index >> level != lastIndex >> level) {\\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n }\\n\\n node = PoseidonT3.hash([node, siblingNodes[i]]);\\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\\n\\n unchecked {\\n ++i;\\n }\\n } else {\\n self.sideNodes[i] = node;\\n }\\n }\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n if (oldRoot != _root(self)) {\\n revert WrongSiblingNodes();\\n }\\n\\n self.sideNodes[treeDepth] = node;\\n\\n if (newLeaf != 0) {\\n self.leaves[newLeaf] = self.leaves[oldLeaf];\\n }\\n\\n self.leaves[oldLeaf] = 0;\\n\\n return node;\\n }\\n\\n /// @dev Removes a leaf from the tree by setting its value to zero.\\n /// This function utilizes the update function to set the leaf's value\\n /// to zero and update the tree's state accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param oldLeaf: The value of the leaf to be removed.\\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\\n /// @return The new root hash of the tree after the leaf has been removed.\\n function _remove(\\n LeanIMTData storage self,\\n uint256 oldLeaf,\\n uint256[] calldata siblingNodes\\n ) internal returns (uint256) {\\n return _update(self, oldLeaf, 0, siblingNodes);\\n }\\n\\n /// @dev Checks if a leaf exists in the tree.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the leaf to check for existence.\\n /// @return A boolean value indicating whether the leaf exists in the tree.\\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\\n return self.leaves[leaf] != 0;\\n }\\n\\n /// @dev Retrieves the index of a given leaf in the tree.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the leaf whose index is to be found.\\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\\n /// reverts with a custom error.\\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\\n if (self.leaves[leaf] == 0) {\\n revert LeafDoesNotExist();\\n }\\n\\n return self.leaves[leaf] - 1;\\n }\\n\\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\\n /// current tree depth.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @return The root hash of the tree.\\n function _root(LeanIMTData storage self) internal view returns (uint256) {\\n return self.sideNodes[self.depth];\\n }\\n}\\n\",\"keccak256\":\"0x6385ce9153d11d9824163464193d4ba3dd304e662dccd365ba2fc381a359762b\",\"license\":\"MIT\"},\"contracts/interfaces/ICiphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface ICiphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeAdded(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeRemoved(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n function isCiphernodeEligible(address ciphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The hash of the public key generated by the given committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKeyHash The hash of the public key of the given committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes32 publicKeyHash);\\n}\\n\",\"keccak256\":\"0xe24e6322e8c6fc83461edfbdbedb409e243f1c4e79021a74585cfe875c225aa2\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IRegistryFilter {\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0x6bd13d0b188e54393b1a030a43f95042161091d49428e880c301d882c4583100\",\"license\":\"LGPL-3.0-only\"},\"contracts/registry/CiphernodeRegistryOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { ICiphernodeRegistry } from \\\"../interfaces/ICiphernodeRegistry.sol\\\";\\nimport { IRegistryFilter } from \\\"../interfaces/IRegistryFilter.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n InternalLeanIMT,\\n LeanIMTData\\n} from \\\"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\\\";\\n\\ncontract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable {\\n using InternalLeanIMT for LeanIMTData;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n address public enclave;\\n uint256 public numCiphernodes;\\n LeanIMTData public ciphernodes;\\n\\n mapping(uint256 e3Id => IRegistryFilter filter) public filters;\\n mapping(uint256 e3Id => uint256 root) public roots;\\n mapping(uint256 e3Id => bytes32 publicKeyHash) public publicKeyHashes;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeAlreadyRequested();\\n error CommitteeAlreadyPublished();\\n error OnlyFilter();\\n error CommitteeNotPublished();\\n error CiphernodeNotEnabled(address node);\\n error OnlyEnclave();\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Modifiers //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n modifier onlyEnclave() {\\n require(msg.sender == enclave, OnlyEnclave());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n constructor(address _owner, address _enclave) {\\n initialize(_owner, _enclave);\\n }\\n\\n function initialize(address _owner, address _enclave) public initializer {\\n __Ownable_init(msg.sender);\\n setEnclave(_enclave);\\n if (_owner != owner()) transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external onlyEnclave returns (bool success) {\\n require(\\n filters[e3Id] == IRegistryFilter(address(0)),\\n CommitteeAlreadyRequested()\\n );\\n filters[e3Id] = IRegistryFilter(filter);\\n roots[e3Id] = root();\\n\\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\\n emit CommitteeRequested(e3Id, filter, threshold);\\n success = true;\\n }\\n\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata,\\n bytes calldata publicKey\\n ) external {\\n // only to be published by the filter\\n require(address(filters[e3Id]) == msg.sender, OnlyFilter());\\n\\n publicKeyHashes[e3Id] = keccak256(publicKey);\\n emit CommitteePublished(e3Id, publicKey);\\n }\\n\\n function addCiphernode(address node) external onlyOwner {\\n uint160 ciphernode = uint160(node);\\n ciphernodes._insert(ciphernode);\\n numCiphernodes++;\\n emit CiphernodeAdded(\\n node,\\n ciphernodes._indexOf(ciphernode),\\n numCiphernodes,\\n ciphernodes.size\\n );\\n }\\n\\n function removeCiphernode(\\n address node,\\n uint256[] calldata siblingNodes\\n ) external onlyOwner {\\n uint160 ciphernode = uint160(node);\\n uint256 index = ciphernodes._indexOf(ciphernode);\\n ciphernodes._remove(ciphernode, siblingNodes);\\n numCiphernodes--;\\n emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setEnclave(address _enclave) public onlyOwner {\\n enclave = _enclave;\\n emit EnclaveSet(_enclave);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes32 publicKeyHash) {\\n publicKeyHash = publicKeyHashes[e3Id];\\n require(publicKeyHash != bytes32(0), CommitteeNotPublished());\\n }\\n\\n function isCiphernodeEligible(address node) external view returns (bool) {\\n return isEnabled(node);\\n }\\n\\n function isEnabled(address node) public view returns (bool) {\\n return ciphernodes._has(uint160(node));\\n }\\n\\n function root() public view returns (uint256) {\\n return (ciphernodes._root());\\n }\\n\\n function rootAt(uint256 e3Id) public view returns (uint256) {\\n return roots[e3Id];\\n }\\n\\n function getFilter(uint256 e3Id) public view returns (IRegistryFilter) {\\n return filters[e3Id];\\n }\\n\\n function treeSize() public view returns (uint256) {\\n return ciphernodes.size;\\n }\\n}\\n\",\"keccak256\":\"0xe911e14c085551d0e3c200279ebf8ce5a70076b68a08303658782b0694593f21\",\"license\":\"LGPL-3.0-only\"},\"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": "0x60803461022457601f6116dc38819003918201601f19168301916001600160401b0383118484101761022957808492604094855283398101031261022457610052602061004b8361023f565b920161023f565b6000805160206116bc83398151915254604081901c60ff16159291906001600160401b0381168015908161021c575b6001149081610212575b159081610209575b506101f8576001600160401b031981166001176000805160206116bc83398151915255836101cd575b506100c56102c9565b6100cd6102c9565b6100d633610253565b6100de6102f7565b600080546001600160a01b0319166001600160a01b039290921691821781557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c99080a260008051602061169c833981519152546001600160a01b03908116908216036101b6575b5061015a575b60405161136e908161032e8239f35b68ff0000000000000000196000805160206116bc83398151915254166000805160206116bc833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a161014b565b6101c7906101c26102f7565b610253565b38610145565b6001600160481b03191668010000000000000001176000805160206116bc83398151915255386100bc565b63f92ee8a960e01b60005260046000fd5b90501538610093565b303b15915061008b565b859150610081565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361022457565b6001600160a01b031680156102b35760008051602061169c83398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff6000805160206116bc8339815191525460401c16156102e657565b631afcd79f60e31b60005260046000fd5b60008051602061169c833981519152546001600160a01b0316330361031857565b63118cdaa760e01b6000523360045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c90816306e341501461108c575080632c92fb99146110575780632e7b716d14610a0b578063485cc95514610e0957806370e36bbe14610da6578063715018a614610d0d5780638a78bb1514610adf5780638cb89ecb14610ab35780638d1ddfb114610a955780638da5cb5b14610a4f5780639015d37114610a0b5780639ccb58d514610897578063a04e606514610387578063c2b40ae41461035b578063ca2869a01461035b578063d9bbec9514610221578063dbb06c93146101fa578063e82f3b70146101b6578063ebf0c71714610184578063f2fde38b14610159578063f379b0df146101345763f6fc05d51461011157600080fd5b3461012f57600036600319011261012f576020600154604051908152f35b600080fd5b3461012f57600036600319011261012f57604060025460035482519182526020820152f35b3461012f57602036600319011261012f576101826101756110bd565b61017d611243565b61119d565b005b3461012f57600036600319011261012f5760206101ae600354600052600460205260406000205490565b604051908152f35b3461012f57602036600319011261012f57600435600052600860205260406000205480156101e957602090604051908152f35b6322e679e360e11b60005260046000fd5b3461012f57600036600319011261012f5760206001600160a01b0360005416604051908152f35b3461012f57606036600319011261012f5760043560243567ffffffffffffffff811161012f576102559036906004016110e9565b505060443567ffffffffffffffff811161012f576102779036906004016110e9565b8260005260066020526001600160a01b0360406000205416330361034a5767ffffffffffffffff811161033457604051601f8201601f1916926102bd6020850183611142565b8282526020820193368483011161012f578460409385847f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc01983760006020878301015251902086600052600860205283600020556000838581519687956020875281602088015283870137840101528101030190a2005b634e487b7160e01b600052604160045260246000fd5b63be19562360e01b60005260046000fd5b3461012f57602036600319011261012f5760043560005260076020526020604060002054604051908152f35b3461012f57604036600319011261012f576103a06110bd565b60243567ffffffffffffffff811161012f573660238201121561012f5780600401359167ffffffffffffffff831161012f576024820191602436918560051b01011161012f576001600160a01b03906103f7611243565b1691610402836112b9565b9161041a846000526005602052604060002054151590565b61042f57631c811d5b60e21b60005260046000fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5461088657610467846112b9565b600092859160025493600019850194851161087257600354948693849392915b87851061054d575050505050506104ab600354600052600460205260406000205490565b0361053c57600052600460205260406000205581600052600560205260006040812055600154908115610526576000199091016001819055600254604080519384526020840192909252908201527f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d59080606081015b0390a2005b634e487b7160e01b600052601160045260246000fd5b631fd4986360e11b60005260046000fd5b90919293949584861c6001808216146000146106ed57507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161059088858761133b565b3510156106dc576105eb6020733333333C0A88F9BE4fd23ed0536F9B6c427e3B939a604051906105bf82611126565b6105ca8b888a61133b565b3582528282015260405180938192632b0aac7f60e11b83526004830161128b565b03818d5af490811561069d576000916106a9575b50610642916020919a6040519161061583611126565b6106208b888a61133b565b358352838301526040518080958194632b0aac7f60e11b83526004830161128b565b03915af490811561069d57600091610668575b50600180919701955b0193929190610487565b906020823d8211610695575b8161068160209383611142565b810103126106925750516001610655565b80fd5b3d9150610674565b6040513d6000823e3d90fd5b906020823d82116106d4575b816106c260209383611142565b810103126106925750516106426105ff565b3d91506106b5565b6361c0541760e11b60005260046000fd5b82871c14610858577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161072188858761133b565b3510156106dc5761077c6020733333333C0A88F9BE4fd23ed0536F9B6c427e3B939a6040519061075082611126565b815261075d8a878961133b565b358282015260405180938192632b0aac7f60e11b83526004830161128b565b03818d5af490811561069d57600091610825575b506107d3916020919a604051916107a683611126565b82526107b38a878961133b565b35838301526040518080958194632b0aac7f60e11b83526004830161128b565b03915af490811561069d576000916107f3575b506001809197019561065e565b906020823d821161081d575b8161080c60209383611142565b8101031261069257505160016107e6565b3d91506107ff565b906020823d8211610850575b8161083e60209383611142565b810103126106925750516107d3610790565b3d9150610831565b95946001908660005260046020528960406000205561065e565b634e487b7160e01b86526011600452602486fd5b6312c50cad60e11b60005260046000fd5b3461012f57608036600319011261012f576004356108b36110d3565b3660841161012f576001600160a01b036000541633036109fa578160005260066020526001600160a01b03604060002054166109e9576001600160a01b03168160005260066020526040600020816001600160a01b0319825416179055610927600354600052600460205260406000205490565b826000526007602052604060002055604051631590527b60e11b815282600482015261095560248201611164565b6020816064816000865af1801561069d576109ae575b5060607fa17377d4a5c0ff5c67888a6b08d9bf3a8505b47e922b6186b259471ebf12738e916040519081526109a260208201611164565ba2602060405160018152f35b6020813d6020116109e1575b816109c760209383611142565b8101031261012f5751801515810361012f5750606061096b565b3d91506109ba565b6374ff462560e11b60005260046000fd5b63e4c2a7eb60e01b60005260046000fd5b3461012f57602036600319011261012f576020610a45610a296110bd565b6001600160a01b03166000526005602052604060002054151590565b6040519015158152f35b3461012f57600036600319011261012f5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b3461012f57600036600319011261012f576020600254604051908152f35b3461012f57602036600319011261012f5760043560005260086020526020604060002054604051908152f35b3461012f57602036600319011261012f576001600160a01b03610b006110bd565b610b08611243565b167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018110610b41576361c0541760e11b60005260046000fd5b80610b57576314b48df160e11b60005260046000fd5b610b6e816000526005602052604060002054151590565b610886576002546003549060ff82116105265760018101808211610526576001831b10610cfd575b81600355829060005b838110610c2e5750610bb090611117565b918260025560005260046020526040600020558160005260056020526040600020557f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db53610bfe600154611117565b80600155610c0b836112b9565b610521600254604051938493846040919493926060820195825260208201520152565b9160018083851c1614600014610ce4576020610c7f9160405190610c5182611126565b856000526004835260406000205482528282015260405180938192632b0aac7f60e11b83526004830161128b565b0381733333333C0A88F9BE4fd23ed0536F9B6c427e3B935af4801561069d57600090610cb2575b60019150925b01610b9f565b6020823d8211610cdc575b81610cca60209383611142565b81010312610692575060019051610ca6565b3d9150610cbd565b9180600191600052600460205283604060002055610cac565b90610d0790611117565b90610b96565b3461012f57600036600319011261012f57610d26611243565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461012f57602036600319011261012f576001600160a01b03610dc76110bd565b610dcf611243565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a2005b3461012f57604036600319011261012f57610e226110bd565b610e2a6110d3565b907ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff82168015908161104f575b6001149081611045575b15908161103c575b5061102b5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556001600160a01b039184610fec575b50610eca6112fb565b610ed26112fb565b610edb3361119d565b610ee3611243565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a26001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b03821603610fda575b50610f5d57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b610fe69061017d611243565b81610f56565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005584610ec1565b63f92ee8a960e01b60005260046000fd5b90501585610e7c565b303b159150610e74565b859150610e6a565b3461012f57602036600319011261012f57600435600052600660205260206001600160a01b0360406000205416604051908152f35b3461012f57602036600319011261012f57602090600435600052600682526001600160a01b03604060002054168152f35b600435906001600160a01b038216820361012f57565b602435906001600160a01b038216820361012f57565b9181601f8401121561012f5782359167ffffffffffffffff831161012f576020838186019501011161012f57565b60001981146105265760010190565b6040810190811067ffffffffffffffff82111761033457604052565b90601f8019910116810190811067ffffffffffffffff82111761033457604052565b60446000915b6002831061117757505050565b81359063ffffffff821680920361012f576020816001938293520192019201919061116a565b6001600160a01b0316801561122d576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361127657565b63118cdaa760e01b6000523360045260246000fd5b919060408301926000905b600282106112a357505050565b6020806001928551815201930191019091611296565b806000526005602052604060002054156112ea57600052600560205260406000205460001981019081116105265790565b631c811d5b60e21b60005260046000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561132a57565b631afcd79f60e31b60005260046000fd5b919081101561134b5760051b0190565b634e487b7160e01b600052603260045260246000fdfea164736f6c634300081b000a9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b60003560e01c90816306e341501461108c575080632c92fb99146110575780632e7b716d14610a0b578063485cc95514610e0957806370e36bbe14610da6578063715018a614610d0d5780638a78bb1514610adf5780638cb89ecb14610ab35780638d1ddfb114610a955780638da5cb5b14610a4f5780639015d37114610a0b5780639ccb58d514610897578063a04e606514610387578063c2b40ae41461035b578063ca2869a01461035b578063d9bbec9514610221578063dbb06c93146101fa578063e82f3b70146101b6578063ebf0c71714610184578063f2fde38b14610159578063f379b0df146101345763f6fc05d51461011157600080fd5b3461012f57600036600319011261012f576020600154604051908152f35b600080fd5b3461012f57600036600319011261012f57604060025460035482519182526020820152f35b3461012f57602036600319011261012f576101826101756110bd565b61017d611243565b61119d565b005b3461012f57600036600319011261012f5760206101ae600354600052600460205260406000205490565b604051908152f35b3461012f57602036600319011261012f57600435600052600860205260406000205480156101e957602090604051908152f35b6322e679e360e11b60005260046000fd5b3461012f57600036600319011261012f5760206001600160a01b0360005416604051908152f35b3461012f57606036600319011261012f5760043560243567ffffffffffffffff811161012f576102559036906004016110e9565b505060443567ffffffffffffffff811161012f576102779036906004016110e9565b8260005260066020526001600160a01b0360406000205416330361034a5767ffffffffffffffff811161033457604051601f8201601f1916926102bd6020850183611142565b8282526020820193368483011161012f578460409385847f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc01983760006020878301015251902086600052600860205283600020556000838581519687956020875281602088015283870137840101528101030190a2005b634e487b7160e01b600052604160045260246000fd5b63be19562360e01b60005260046000fd5b3461012f57602036600319011261012f5760043560005260076020526020604060002054604051908152f35b3461012f57604036600319011261012f576103a06110bd565b60243567ffffffffffffffff811161012f573660238201121561012f5780600401359167ffffffffffffffff831161012f576024820191602436918560051b01011161012f576001600160a01b03906103f7611243565b1691610402836112b9565b9161041a846000526005602052604060002054151590565b61042f57631c811d5b60e21b60005260046000fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5461088657610467846112b9565b600092859160025493600019850194851161087257600354948693849392915b87851061054d575050505050506104ab600354600052600460205260406000205490565b0361053c57600052600460205260406000205581600052600560205260006040812055600154908115610526576000199091016001819055600254604080519384526020840192909252908201527f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d59080606081015b0390a2005b634e487b7160e01b600052601160045260246000fd5b631fd4986360e11b60005260046000fd5b90919293949584861c6001808216146000146106ed57507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161059088858761133b565b3510156106dc576105eb602073__$75f79a42d9bcbdbb69ad79ebd80f556f39$__9a604051906105bf82611126565b6105ca8b888a61133b565b3582528282015260405180938192632b0aac7f60e11b83526004830161128b565b03818d5af490811561069d576000916106a9575b50610642916020919a6040519161061583611126565b6106208b888a61133b565b358352838301526040518080958194632b0aac7f60e11b83526004830161128b565b03915af490811561069d57600091610668575b50600180919701955b0193929190610487565b906020823d8211610695575b8161068160209383611142565b810103126106925750516001610655565b80fd5b3d9150610674565b6040513d6000823e3d90fd5b906020823d82116106d4575b816106c260209383611142565b810103126106925750516106426105ff565b3d91506106b5565b6361c0541760e11b60005260046000fd5b82871c14610858577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161072188858761133b565b3510156106dc5761077c602073__$75f79a42d9bcbdbb69ad79ebd80f556f39$__9a6040519061075082611126565b815261075d8a878961133b565b358282015260405180938192632b0aac7f60e11b83526004830161128b565b03818d5af490811561069d57600091610825575b506107d3916020919a604051916107a683611126565b82526107b38a878961133b565b35838301526040518080958194632b0aac7f60e11b83526004830161128b565b03915af490811561069d576000916107f3575b506001809197019561065e565b906020823d821161081d575b8161080c60209383611142565b8101031261069257505160016107e6565b3d91506107ff565b906020823d8211610850575b8161083e60209383611142565b810103126106925750516107d3610790565b3d9150610831565b95946001908660005260046020528960406000205561065e565b634e487b7160e01b86526011600452602486fd5b6312c50cad60e11b60005260046000fd5b3461012f57608036600319011261012f576004356108b36110d3565b3660841161012f576001600160a01b036000541633036109fa578160005260066020526001600160a01b03604060002054166109e9576001600160a01b03168160005260066020526040600020816001600160a01b0319825416179055610927600354600052600460205260406000205490565b826000526007602052604060002055604051631590527b60e11b815282600482015261095560248201611164565b6020816064816000865af1801561069d576109ae575b5060607fa17377d4a5c0ff5c67888a6b08d9bf3a8505b47e922b6186b259471ebf12738e916040519081526109a260208201611164565ba2602060405160018152f35b6020813d6020116109e1575b816109c760209383611142565b8101031261012f5751801515810361012f5750606061096b565b3d91506109ba565b6374ff462560e11b60005260046000fd5b63e4c2a7eb60e01b60005260046000fd5b3461012f57602036600319011261012f576020610a45610a296110bd565b6001600160a01b03166000526005602052604060002054151590565b6040519015158152f35b3461012f57600036600319011261012f5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b3461012f57600036600319011261012f576020600254604051908152f35b3461012f57602036600319011261012f5760043560005260086020526020604060002054604051908152f35b3461012f57602036600319011261012f576001600160a01b03610b006110bd565b610b08611243565b167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018110610b41576361c0541760e11b60005260046000fd5b80610b57576314b48df160e11b60005260046000fd5b610b6e816000526005602052604060002054151590565b610886576002546003549060ff82116105265760018101808211610526576001831b10610cfd575b81600355829060005b838110610c2e5750610bb090611117565b918260025560005260046020526040600020558160005260056020526040600020557f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db53610bfe600154611117565b80600155610c0b836112b9565b610521600254604051938493846040919493926060820195825260208201520152565b9160018083851c1614600014610ce4576020610c7f9160405190610c5182611126565b856000526004835260406000205482528282015260405180938192632b0aac7f60e11b83526004830161128b565b038173__$75f79a42d9bcbdbb69ad79ebd80f556f39$__5af4801561069d57600090610cb2575b60019150925b01610b9f565b6020823d8211610cdc575b81610cca60209383611142565b81010312610692575060019051610ca6565b3d9150610cbd565b9180600191600052600460205283604060002055610cac565b90610d0790611117565b90610b96565b3461012f57600036600319011261012f57610d26611243565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461012f57602036600319011261012f576001600160a01b03610dc76110bd565b610dcf611243565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a2005b3461012f57604036600319011261012f57610e226110bd565b610e2a6110d3565b907ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff82168015908161104f575b6001149081611045575b15908161103c575b5061102b5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556001600160a01b039184610fec575b50610eca6112fb565b610ed26112fb565b610edb3361119d565b610ee3611243565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a26001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b03821603610fda575b50610f5d57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b610fe69061017d611243565b81610f56565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005584610ec1565b63f92ee8a960e01b60005260046000fd5b90501585610e7c565b303b159150610e74565b859150610e6a565b3461012f57602036600319011261012f57600435600052600660205260206001600160a01b0360406000205416604051908152f35b3461012f57602036600319011261012f57602090600435600052600682526001600160a01b03604060002054168152f35b600435906001600160a01b038216820361012f57565b602435906001600160a01b038216820361012f57565b9181601f8401121561012f5782359167ffffffffffffffff831161012f576020838186019501011161012f57565b60001981146105265760010190565b6040810190811067ffffffffffffffff82111761033457604052565b90601f8019910116810190811067ffffffffffffffff82111761033457604052565b60446000915b6002831061117757505050565b81359063ffffffff821680920361012f576020816001938293520192019201919061116a565b6001600160a01b0316801561122d576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361127657565b63118cdaa760e01b6000523360045260246000fd5b919060408301926000905b600282106112a357505050565b6020806001928551815201930191019091611296565b806000526005602052604060002054156112ea57600052600560205260406000205460001981019081116105265790565b631c811d5b60e21b60005260046000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561132a57565b631afcd79f60e31b60005260046000fd5b919081101561134b5760051b0190565b634e487b7160e01b600052603260045260246000fdfea164736f6c634300081b000a", - "libraries": { - "PoseidonT3": "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93" - }, - "devdoc": { - "errors": { - "InvalidInitialization()": [ - { - "details": "The contract is already initialized." - } - ], - "NotInitializing()": [ - { - "details": "The contract is not initializing." - } - ], - "OwnableInvalidOwner(address)": [ - { - "details": "The owner is not a valid owner account. (eg. `address(0)`)" - } - ], - "OwnableUnauthorizedAccount(address)": [ - { - "details": "The caller account is not authorized to perform an operation." - } - ] - }, - "events": { - "CiphernodeAdded(address,uint256,uint256,uint256)": { - "params": { - "index": "Index of the ciphernode in the registry.", - "node": "Address of the ciphernode.", - "numNodes": "Number of ciphernodes in the registry.", - "size": "Size of the registry." - } - }, - "CiphernodeRemoved(address,uint256,uint256,uint256)": { - "params": { - "index": "Index of the ciphernode in the registry.", - "node": "Address of the ciphernode.", - "numNodes": "Number of ciphernodes in the registry.", - "size": "Size of the registry." - } - }, - "CommitteePublished(uint256,bytes)": { - "params": { - "e3Id": "ID of the E3 for which the committee was selected.", - "publicKey": "Public key of the committee." - } - }, - "CommitteeRequested(uint256,address,uint32[2])": { - "params": { - "e3Id": "ID of the E3 for which the committee was selected.", - "filter": "Address of the contract that will coordinate committee selection.", - "threshold": "The M/N threshold for the committee." - } - }, - "EnclaveSet(address)": { - "params": { - "enclave": "Address of the enclave contract." - } - }, - "Initialized(uint64)": { - "details": "Triggered when the contract has been initialized or reinitialized." - } - }, - "kind": "dev", - "methods": { - "committeePublicKey(uint256)": { - "details": "This function MUST revert if no committee has been requested for the given E3.This function MUST revert if the committee has not yet published a public key.", - "params": { - "e3Id": "ID of the E3 for which to get the committee public key." - }, - "returns": { - "publicKeyHash": "The hash of the public key of the given committee." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." - }, - "requestCommittee(uint256,address,uint32[2])": { - "details": "This function MUST revert when not called by the Enclave contract.", - "params": { - "e3Id": "ID of the E3 for which to select the committee.", - "filter": "The address of the filter responsible for the committee selection process.", - "threshold": "The M/N threshold for the committee." - }, - "returns": { - "success": "True if committee selection was successfully initiated." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "version": 1 - }, - "userdoc": { - "events": { - "CiphernodeAdded(address,uint256,uint256,uint256)": { - "notice": "This event MUST be emitted when a ciphernode is added to the registry." - }, - "CiphernodeRemoved(address,uint256,uint256,uint256)": { - "notice": "This event MUST be emitted when a ciphernode is removed from the registry." - }, - "CommitteePublished(uint256,bytes)": { - "notice": "This event MUST be emitted when a committee is selected for an E3." - }, - "CommitteeRequested(uint256,address,uint32[2])": { - "notice": "This event MUST be emitted when a committee is selected for an E3." - }, - "EnclaveSet(address)": { - "notice": "This event MUST be emitted when `enclave` is set." - } - }, - "kind": "user", - "methods": { - "committeePublicKey(uint256)": { - "notice": "This function should be called by the Enclave contract to get the public key of a committee." - }, - "requestCommittee(uint256,address,uint32[2])": { - "notice": "Initiates the committee selection process for a specified E3." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 3683, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "enclave", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 3685, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "numCiphernodes", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 3688, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "ciphernodes", - "offset": 0, - "slot": "2", - "type": "t_struct(LeanIMTData)1294_storage" - }, - { - "astId": 3693, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "filters", - "offset": 0, - "slot": "6", - "type": "t_mapping(t_uint256,t_contract(IRegistryFilter)3662)" - }, - { - "astId": 3697, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "roots", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 3701, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "publicKeyHashes", - "offset": 0, - "slot": "8", - "type": "t_mapping(t_uint256,t_bytes32)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IRegistryFilter)3662": { - "encoding": "inplace", - "label": "contract IRegistryFilter", - "numberOfBytes": "20" - }, - "t_mapping(t_uint256,t_bytes32)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bytes32)", - "numberOfBytes": "32", - "value": "t_bytes32" - }, - "t_mapping(t_uint256,t_contract(IRegistryFilter)3662)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => contract IRegistryFilter)", - "numberOfBytes": "32", - "value": "t_contract(IRegistryFilter)3662" - }, - "t_mapping(t_uint256,t_uint256)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_struct(LeanIMTData)1294_storage": { - "encoding": "inplace", - "label": "struct LeanIMTData", - "members": [ - { - "astId": 1283, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "size", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 1285, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "depth", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 1289, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "sideNodes", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 1293, - "contract": "contracts/registry/CiphernodeRegistryOwnable.sol:CiphernodeRegistryOwnable", - "label": "leaves", - "offset": 0, - "slot": "3", - "type": "t_mapping(t_uint256,t_uint256)" - } - ], - "numberOfBytes": "128" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/Enclave.json b/packages/enclave-contracts/deployments/sepolia/Enclave.json deleted file mode 100644 index 1d6de1db32..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/Enclave.json +++ /dev/null @@ -1,2026 +0,0 @@ -{ - "address": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "contract ICiphernodeRegistry", - "name": "_ciphernodeRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_maxDuration", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "CiphertextOutputAlreadyPublished", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "CiphertextOutputNotPublished", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeSelectionFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "E3AlreadyActivated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "E3DoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "E3Expired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "E3NotActivated", - "type": "error" - }, - { - "inputs": [], - "name": "E3NotReady", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "E3ProgramNotAllowed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "InputDeadlineNotPassed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "InputDeadlinePassed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "contract ICiphernodeRegistry", - "name": "ciphernodeRegistry", - "type": "address" - } - ], - "name": "InvalidCiphernodeRegistry", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - } - ], - "name": "InvalidComputationRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - } - ], - "name": "InvalidDuration", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "InvalidEncryptionScheme", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInput", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "output", - "type": "bytes" - } - ], - "name": "InvalidOutput", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidStartWindow", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - } - ], - "name": "InvalidThreshold", - "type": "error" - }, - { - "inputs": [], - "name": "LeafAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "LeafCannotBeZero", - "type": "error" - }, - { - "inputs": [], - "name": "LeafGreaterThanSnarkScalarField", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "ModuleAlreadyEnabled", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "ModuleNotEnabled", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "PaymentRequired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "PlaintextOutputAlreadyPublished", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "ciphernodeRegistry", - "type": "address" - } - ], - "name": "CiphernodeRegistrySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "ciphertextOutput", - "type": "bytes" - } - ], - "name": "CiphertextOutputPublished", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "committeePublicKey", - "type": "bytes" - } - ], - "name": "E3Activated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "E3ProgramDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "E3ProgramEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - }, - { - "internalType": "uint256", - "name": "requestBlock", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "startWindow", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - }, - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "committeePublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "ciphertextOutput", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - } - ], - "indexed": false, - "internalType": "struct E3", - "name": "e3", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "address", - "name": "filter", - "type": "address" - }, - { - "indexed": true, - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "E3Requested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "EncryptionSchemeDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "EncryptionSchemeEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "inputHash", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "InputPublished", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "maxDuration", - "type": "uint256" - } - ], - "name": "MaxDurationSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - } - ], - "name": "PlaintextOutputPublished", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - } - ], - "name": "activate", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "ciphernodeRegistry", - "outputs": [ - { - "internalType": "contract ICiphernodeRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "decryptionVerifiers", - "outputs": [ - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "disableE3Program", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "disableEncryptionScheme", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "e3Programs", - "outputs": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "e3s", - "outputs": [ - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - }, - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "committeePublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "ciphertextOutput", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - } - ], - "name": "enableE3Program", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - } - ], - "name": "getDecryptionVerifier", - "outputs": [ - { - "internalType": "contract IDecryptionVerifier", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "getE3", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - }, - { - "internalType": "uint256", - "name": "requestBlock", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "startWindow", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - }, - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "committeePublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "ciphertextOutput", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - } - ], - "internalType": "struct E3", - "name": "e3", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "getInputRoot", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "contract ICiphernodeRegistry", - "name": "_ciphernodeRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_maxDuration", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "inputCounts", - "outputs": [ - { - "internalType": "uint256", - "name": "inputCount", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "inputs", - "outputs": [ - { - "internalType": "uint256", - "name": "size", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "depth", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "nexte3Id", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "ciphertextOutput", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - } - ], - "name": "publishCiphertextOutput", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "publishInput", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - } - ], - "name": "publishPlaintextOutput", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "filter", - "type": "address" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - }, - { - "internalType": "uint256[2]", - "name": "startWindow", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - }, - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "computeProviderParams", - "type": "bytes" - } - ], - "name": "request", - "outputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - }, - { - "internalType": "uint256", - "name": "requestBlock", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "startWindow", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "duration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - }, - { - "internalType": "contract IE3Program", - "name": "e3Program", - "type": "address" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "committeePublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "ciphertextOutput", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "plaintextOutput", - "type": "bytes" - } - ], - "internalType": "struct E3", - "name": "e3", - "type": "tuple" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "requests", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ICiphernodeRegistry", - "name": "_ciphernodeRegistry", - "type": "address" - } - ], - "name": "setCiphernodeRegistry", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionSchemeId", - "type": "bytes32" - }, - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - } - ], - "name": "setDecryptionVerifier", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_maxDuration", - "type": "uint256" - } - ], - "name": "setMaxDuration", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "transactionIndex": 321, - "gasUsed": "2177587", - "logsBloom": "0x00000000000000000000000000000000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000001000000001000000000100000000000000000020000000000000000000800000000000000000000000000000400420000000000000000000800000000000000000000004080000000000000000000000000000000000000000000000000000000000000000000004000000000000000000020000000010000000000000000000000000004000000000000000020000000000000000000000000000001000000000800000000000000000000000000", - "blockHash": "0xd72f5ec2bb616c64c8f5bbf6802669638ee6244ce86aec2a47250ac3173c82f4", - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "logs": [ - { - "transactionIndex": 321, - "blockNumber": 8360698, - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "address": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000008837e47c4bb520ade83aab761c3b60679443af1b" - ], - "data": "0x", - "logIndex": 469, - "blockHash": "0xd72f5ec2bb616c64c8f5bbf6802669638ee6244ce86aec2a47250ac3173c82f4" - }, - { - "transactionIndex": 321, - "blockNumber": 8360698, - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "address": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "topics": [ - "0xba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000278d00", - "logIndex": 470, - "blockHash": "0xd72f5ec2bb616c64c8f5bbf6802669638ee6244ce86aec2a47250ac3173c82f4" - }, - { - "transactionIndex": 321, - "blockNumber": 8360698, - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "address": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "topics": [ - "0x80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b6" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 471, - "blockHash": "0xd72f5ec2bb616c64c8f5bbf6802669638ee6244ce86aec2a47250ac3173c82f4" - }, - { - "transactionIndex": 321, - "blockNumber": 8360698, - "transactionHash": "0x6c1ef01dba2714a518dca4fd47afa33ea9b0f7903e67e69613be23c8332535d1", - "address": "0x6307a84B88F2641f197359a95BC6029bF33f54fb", - "topics": [ - "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 472, - "blockHash": "0xd72f5ec2bb616c64c8f5bbf6802669638ee6244ce86aec2a47250ac3173c82f4" - } - ], - "blockNumber": 8360698, - "cumulativeGasUsed": "28107948", - "status": 1, - "byzantium": true - }, - "args": [ - "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "0x0000000000000000000000000000000000000001", - 2592000 - ], - "numDeployments": 3, - "solcInputHash": "1560ab6aa11f44088d4445eb3d74156d", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"contract ICiphernodeRegistry\",\"name\":\"_ciphernodeRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"CiphertextOutputAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"CiphertextOutputNotPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeSelectionFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3AlreadyActivated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3DoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"E3Expired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3NotActivated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"E3NotReady\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"E3ProgramNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"InputDeadlineNotPassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"InputDeadlinePassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract ICiphernodeRegistry\",\"name\":\"ciphernodeRegistry\",\"type\":\"address\"}],\"name\":\"InvalidCiphernodeRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"}],\"name\":\"InvalidComputationRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"InvalidDuration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"InvalidEncryptionScheme\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"output\",\"type\":\"bytes\"}],\"name\":\"InvalidOutput\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStartWindow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"InvalidThreshold\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeafGreaterThanSnarkScalarField\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"ModuleAlreadyEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"ModuleNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PaymentRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"PlaintextOutputAlreadyPublished\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ciphernodeRegistry\",\"type\":\"address\"}],\"name\":\"CiphernodeRegistrySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"}],\"name\":\"CiphertextOutputPublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"}],\"name\":\"E3Activated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"E3ProgramDisabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"E3ProgramEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256\",\"name\":\"requestBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"},{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"committeePublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"ciphertextOutput\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"E3Requested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"EncryptionSchemeDisabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"EncryptionSchemeEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inputHash\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InputPublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxDuration\",\"type\":\"uint256\"}],\"name\":\"MaxDurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"name\":\"PlaintextOutputPublished\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"activate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ciphernodeRegistry\",\"outputs\":[{\"internalType\":\"contract ICiphernodeRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"decryptionVerifiers\",\"outputs\":[{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"disableE3Program\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"disableEncryptionScheme\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"e3Programs\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"e3s\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"},{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"committeePublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"ciphertextOutput\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"}],\"name\":\"enableE3Program\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"}],\"name\":\"getDecryptionVerifier\",\"outputs\":[{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"getE3\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256\",\"name\":\"requestBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"},{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"committeePublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"ciphertextOutput\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"getInputRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"contract ICiphernodeRegistry\",\"name\":\"_ciphernodeRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"inputCounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"inputCount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"inputs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"depth\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nexte3Id\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"publishCiphertextOutput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"publishInput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"publishPlaintextOutput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"computeProviderParams\",\"type\":\"bytes\"}],\"name\":\"request\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256\",\"name\":\"requestBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"},{\"internalType\":\"contract IE3Program\",\"name\":\"e3Program\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"committeePublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"ciphertextOutput\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requests\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ICiphernodeRegistry\",\"name\":\"_ciphernodeRegistry\",\"type\":\"address\"}],\"name\":\"setCiphernodeRegistry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionSchemeId\",\"type\":\"bytes32\"},{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"}],\"name\":\"setDecryptionVerifier\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"name\":\"setMaxDuration\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"CiphernodeRegistrySet(address)\":{\"params\":{\"ciphernodeRegistry\":\"The address of the CiphernodeRegistry contract.\"}},\"CiphertextOutputPublished(uint256,bytes)\":{\"params\":{\"ciphertextOutput\":\"ABI encoded ciphertext output.\",\"e3Id\":\"ID of the E3.\"}},\"E3Activated(uint256,uint256,bytes)\":{\"params\":{\"committeePublicKey\":\"Public key of the committee.\",\"e3Id\":\"ID of the E3.\",\"expiration\":\"Timestamp when committee duties expire.\"}},\"E3ProgramDisabled(address)\":{\"params\":{\"e3Program\":\"The address of the E3 Program.\"}},\"E3ProgramEnabled(address)\":{\"params\":{\"e3Program\":\"The address of the E3 Program.\"}},\"E3Requested(uint256,(uint256,uint32[2],uint256,uint256[2],uint256,uint256,bytes32,address,bytes,address,address,bytes32,bytes32,bytes),address,address)\":{\"params\":{\"e3\":\"Details of the E3.\",\"e3Id\":\"ID of the E3.\",\"e3Program\":\"Address of the Computation module selected.\",\"filter\":\"Address of the pool of nodes from which the Cipher Node committee was selected.\"}},\"EncryptionSchemeDisabled(bytes32)\":{\"params\":{\"encryptionSchemeId\":\"The ID of the encryption scheme that was disabled.\"}},\"EncryptionSchemeEnabled(bytes32)\":{\"params\":{\"encryptionSchemeId\":\"The ID of the encryption scheme that was enabled.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"InputPublished(uint256,bytes,uint256,uint256)\":{\"params\":{\"data\":\"ABI encoded input data.\",\"e3Id\":\"ID of the E3.\"}},\"MaxDurationSet(uint256)\":{\"params\":{\"maxDuration\":\"The maximum duration of a computation in seconds.\"}},\"PlaintextOutputPublished(uint256,bytes)\":{\"params\":{\"e3Id\":\"ID of the E3.\",\"plaintextOutput\":\"ABI encoded plaintext output.\"}}},\"kind\":\"dev\",\"methods\":{\"activate(uint256,bytes)\":{\"details\":\"This function MUST emit the E3Activated event.This function MUST revert if the given E3 has not yet been requested.This function MUST revert if the selected node committee has not yet published a public key.\",\"params\":{\"e3Id\":\"ID of the E3.\",\"publicKey\":\"Public key of the committee.\"},\"returns\":{\"success\":\"True if the E3 was successfully activated.\"}},\"constructor\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds\",\"_owner\":\"The owner of this contract\"}},\"getE3(uint256)\":{\"details\":\"This function MUST revert if the E3 does not exist.\",\"params\":{\"e3Id\":\"ID of the E3.\"},\"returns\":{\"e3\":\"The struct representing the requested E3.\"}},\"getInputRoot(uint256)\":{\"details\":\"This function MUST revert if the E3 does not exist.\",\"params\":{\"e3Id\":\"ID of the E3.\"},\"returns\":{\"_0\":\"The root of the input merkle tree.\"}},\"initialize(address,address,uint256)\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds\",\"_owner\":\"The owner of this contract\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"publishCiphertextOutput(uint256,bytes,bytes)\":{\"details\":\"This function MUST emit the CiphertextOutputPublished event.\",\"params\":{\"ciphertextOutput\":\"ABI encoded output data to verify.\",\"e3Id\":\"ID of the E3.\",\"proof\":\"ABI encoded data to verify the ciphertextOutput.\"},\"returns\":{\"success\":\"True if the output was successfully published.\"}},\"publishInput(uint256,bytes)\":{\"details\":\"This function MUST revert if the E3 is not yet activated.This function MUST emit the InputPublished event.\",\"params\":{\"data\":\"ABI encoded input data to publish.\",\"e3Id\":\"ID of the E3.\"},\"returns\":{\"success\":\"True if the input was successfully published.\"}},\"publishPlaintextOutput(uint256,bytes,bytes)\":{\"details\":\"This function MUST revert if the output has not been published.This function MUST emit the PlaintextOutputPublished event.\",\"params\":{\"e3Id\":\"ID of the E3.\",\"plaintextOutput\":\"ABI encoded plaintext output.\",\"proof\":\"ABI encoded data to verify the plaintextOutput.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"request(address,uint32[2],uint256[2],uint256,address,bytes,bytes)\":{\"details\":\"This function MUST emit the E3Requested event.\",\"params\":{\"computeProviderParams\":\"ABI encoded compute provider parameters.\",\"duration\":\"The duration of the computation in seconds.\",\"e3Program\":\"Address of the E3 Program.\",\"e3ProgramParams\":\"ABI encoded computation parameters.\",\"filter\":\"IDs of the pool of nodes from which to select the committee.\",\"threshold\":\"The M/N threshold for the committee.\"},\"returns\":{\"e3\":\"The E3 struct.\",\"e3Id\":\"ID of the E3.\"}},\"setMaxDuration(uint256)\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds.\"},\"returns\":{\"success\":\"True if the max duration was successfully set.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"CiphernodeRegistrySet(address)\":{\"notice\":\"This event MUST be emitted any time the CiphernodeRegistry is set.\"},\"CiphertextOutputPublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published.\"},\"E3Activated(uint256,uint256,bytes)\":{\"notice\":\"This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\"},\"E3ProgramDisabled(address)\":{\"notice\":\"This event MUST be emitted any time a E3 Program is disabled.\"},\"E3ProgramEnabled(address)\":{\"notice\":\"This event MUST be emitted any time a E3 Program is enabled.\"},\"E3Requested(uint256,(uint256,uint32[2],uint256,uint256[2],uint256,uint256,bytes32,address,bytes,address,address,bytes32,bytes32,bytes),address,address)\":{\"notice\":\"This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\"},\"EncryptionSchemeDisabled(bytes32)\":{\"notice\":\"This event MUST be emitted any time an encryption scheme is disabled.\"},\"EncryptionSchemeEnabled(bytes32)\":{\"notice\":\"The event MUST be emitted any time an encryption scheme is enabled.\"},\"InputPublished(uint256,bytes,uint256,uint256)\":{\"notice\":\"This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published.\"},\"MaxDurationSet(uint256)\":{\"notice\":\"This event MUST be emitted any time the `maxDuration` is set.\"},\"PlaintextOutputPublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published.\"}},\"kind\":\"user\",\"methods\":{\"activate(uint256,bytes)\":{\"notice\":\"This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input.\"},\"getE3(uint256)\":{\"notice\":\"This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\"},\"getInputRoot(uint256)\":{\"notice\":\"This function returns root of the input merkle tree for a given E3.\"},\"publishCiphertextOutput(uint256,bytes,bytes)\":{\"notice\":\"This function should be called to publish output data for an Encrypted Execution Environment (E3).\"},\"publishInput(uint256,bytes)\":{\"notice\":\"This function should be called to publish input data for Encrypted Execution Environment (E3).\"},\"publishPlaintextOutput(uint256,bytes,bytes)\":{\"notice\":\"This function publishes the plaintext output of an Encrypted Execution Environment (E3).\"},\"request(address,uint32[2],uint256[2],uint256,address,bytes,bytes)\":{\"notice\":\"This function should be called to request a computation within an Encrypted Execution Environment (E3).\"},\"setMaxDuration(uint256)\":{\"notice\":\"This function should be called to set the maximum duration of requested computations.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Enclave.sol\":\"Enclave\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"@zk-kit/lean-imt.sol/Constants.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.4;\\n\\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\\n\",\"keccak256\":\"0xb1944a1d9f63069b2f22260935adb2d11546f82fbb7d12d853a90134a92f4b5b\",\"license\":\"UNLICENSED\"},\"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {PoseidonT3} from \\\"poseidon-solidity/PoseidonT3.sol\\\";\\nimport {SNARK_SCALAR_FIELD} from \\\"./Constants.sol\\\";\\n\\nstruct LeanIMTData {\\n // Tracks the current number of leaves in the tree.\\n uint256 size;\\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\\n uint256 depth;\\n // A mapping from each level of the tree to the node value of the last even position at that level.\\n // Used for efficient inserts, updates and root calculations.\\n mapping(uint256 => uint256) sideNodes;\\n // A mapping from leaf values to their respective indices in the tree.\\n // This facilitates checks for leaf existence and retrieval of leaf positions.\\n mapping(uint256 => uint256) leaves;\\n}\\n\\nerror WrongSiblingNodes();\\nerror LeafGreaterThanSnarkScalarField();\\nerror LeafCannotBeZero();\\nerror LeafAlreadyExists();\\nerror LeafDoesNotExist();\\n\\n/// @title Lean Incremental binary Merkle tree.\\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\\n/// it is updated based on the number of leaves in the tree. This approach\\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\\nlibrary InternalLeanIMT {\\n /// @dev Inserts a new leaf into the incremental merkle tree.\\n /// The function ensures that the leaf is valid according to the\\n /// constraints of the tree and then updates the tree's structure accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the new leaf to be inserted into the tree.\\n /// @return The new hash of the node after the leaf has been inserted.\\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\\n if (leaf >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (leaf == 0) {\\n revert LeafCannotBeZero();\\n } else if (_has(self, leaf)) {\\n revert LeafAlreadyExists();\\n }\\n\\n uint256 index = self.size;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n // A new insertion can increase a tree's depth by at most 1,\\n // and only if the number of leaves supported by the current\\n // depth is less than the number of leaves to be supported after insertion.\\n if (2 ** treeDepth < index + 1) {\\n ++treeDepth;\\n }\\n\\n self.depth = treeDepth;\\n\\n uint256 node = leaf;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n if ((index >> level) & 1 == 1) {\\n node = PoseidonT3.hash([self.sideNodes[level], node]);\\n } else {\\n self.sideNodes[level] = node;\\n }\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n self.size = ++index;\\n\\n self.sideNodes[treeDepth] = node;\\n self.leaves[leaf] = index;\\n\\n return node;\\n }\\n\\n /// @dev Inserts many leaves into the incremental merkle tree.\\n /// The function ensures that the leaves are valid according to the\\n /// constraints of the tree and then updates the tree's structure accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaves: The values of the new leaves to be inserted into the tree.\\n /// @return The root after the leaves have been inserted.\\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\\n // Cache tree size to optimize gas\\n uint256 treeSize = self.size;\\n\\n // Check that all the new values are correct to be added.\\n for (uint256 i = 0; i < leaves.length; ) {\\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (leaves[i] == 0) {\\n revert LeafCannotBeZero();\\n } else if (_has(self, leaves[i])) {\\n revert LeafAlreadyExists();\\n }\\n\\n self.leaves[leaves[i]] = treeSize + 1 + i;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Array to save the nodes that will be used to create the next level of the tree.\\n uint256[] memory currentLevelNewNodes;\\n\\n currentLevelNewNodes = leaves;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n // Calculate the depth of the tree after adding the new values.\\n // Unlike the 'insert' function, we need a while here as\\n // N insertions can increase the tree's depth more than once.\\n while (2 ** treeDepth < treeSize + leaves.length) {\\n ++treeDepth;\\n }\\n\\n self.depth = treeDepth;\\n\\n // First index to change in every level.\\n uint256 currentLevelStartIndex = treeSize;\\n\\n // Size of the level used to create the next level.\\n uint256 currentLevelSize = treeSize + leaves.length;\\n\\n // The index where changes begin at the next level.\\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\\n\\n // The size of the next level.\\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n // The number of nodes for the new level that will be created,\\n // only the new values, not the entire level.\\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\\n for (uint256 i = 0; i < numberOfNewNodes; ) {\\n uint256 leftNode;\\n\\n // Assign the left node using the saved path or the position in the array.\\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\\n leftNode = self.sideNodes[level];\\n } else {\\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\\n }\\n\\n uint256 rightNode;\\n\\n // Assign the right node if the value exists.\\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\\n }\\n\\n uint256 parentNode;\\n\\n // Assign the parent node.\\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\\n // it will be the leftNode.\\n if (rightNode != 0) {\\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\\n } else {\\n parentNode = leftNode;\\n }\\n\\n nextLevelNewNodes[i] = parentNode;\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Update the `sideNodes` variable.\\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\\n // will be the value before the last one.\\n // If it is even and there is only one element, there is no need to save anything because\\n // the correct value for this level was already saved before.\\n if (currentLevelSize & 1 == 1) {\\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\\n } else if (currentLevelNewNodes.length > 1) {\\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\\n }\\n\\n currentLevelStartIndex = nextLevelStartIndex;\\n\\n // Calculate the next level startIndex value.\\n // It is the position of the parent node which is pos/2.\\n nextLevelStartIndex >>= 1;\\n\\n // Update the next array that will be used to calculate the next level.\\n currentLevelNewNodes = nextLevelNewNodes;\\n\\n currentLevelSize = nextLevelSize;\\n\\n // Calculate the size of the next level.\\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n // Update tree size\\n self.size = treeSize + leaves.length;\\n\\n // Update tree root\\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\\n\\n return currentLevelNewNodes[0];\\n }\\n\\n /// @dev Updates the value of an existing leaf and recalculates hashes\\n /// to maintain tree integrity.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param oldLeaf: The value of the leaf that is to be updated.\\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\\n /// @return The new hash of the updated node after the leaf has been updated.\\n function _update(\\n LeanIMTData storage self,\\n uint256 oldLeaf,\\n uint256 newLeaf,\\n uint256[] calldata siblingNodes\\n ) internal returns (uint256) {\\n if (newLeaf >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n } else if (!_has(self, oldLeaf)) {\\n revert LeafDoesNotExist();\\n } else if (_has(self, newLeaf)) {\\n revert LeafAlreadyExists();\\n }\\n\\n uint256 index = _indexOf(self, oldLeaf);\\n uint256 node = newLeaf;\\n uint256 oldRoot = oldLeaf;\\n\\n uint256 lastIndex = self.size - 1;\\n uint256 i = 0;\\n\\n // Cache tree depth to optimize gas\\n uint256 treeDepth = self.depth;\\n\\n for (uint256 level = 0; level < treeDepth; ) {\\n if ((index >> level) & 1 == 1) {\\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n }\\n\\n node = PoseidonT3.hash([siblingNodes[i], node]);\\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\\n\\n unchecked {\\n ++i;\\n }\\n } else {\\n if (index >> level != lastIndex >> level) {\\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\\n revert LeafGreaterThanSnarkScalarField();\\n }\\n\\n node = PoseidonT3.hash([node, siblingNodes[i]]);\\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\\n\\n unchecked {\\n ++i;\\n }\\n } else {\\n self.sideNodes[i] = node;\\n }\\n }\\n\\n unchecked {\\n ++level;\\n }\\n }\\n\\n if (oldRoot != _root(self)) {\\n revert WrongSiblingNodes();\\n }\\n\\n self.sideNodes[treeDepth] = node;\\n\\n if (newLeaf != 0) {\\n self.leaves[newLeaf] = self.leaves[oldLeaf];\\n }\\n\\n self.leaves[oldLeaf] = 0;\\n\\n return node;\\n }\\n\\n /// @dev Removes a leaf from the tree by setting its value to zero.\\n /// This function utilizes the update function to set the leaf's value\\n /// to zero and update the tree's state accordingly.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param oldLeaf: The value of the leaf to be removed.\\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\\n /// @return The new root hash of the tree after the leaf has been removed.\\n function _remove(\\n LeanIMTData storage self,\\n uint256 oldLeaf,\\n uint256[] calldata siblingNodes\\n ) internal returns (uint256) {\\n return _update(self, oldLeaf, 0, siblingNodes);\\n }\\n\\n /// @dev Checks if a leaf exists in the tree.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the leaf to check for existence.\\n /// @return A boolean value indicating whether the leaf exists in the tree.\\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\\n return self.leaves[leaf] != 0;\\n }\\n\\n /// @dev Retrieves the index of a given leaf in the tree.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @param leaf: The value of the leaf whose index is to be found.\\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\\n /// reverts with a custom error.\\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\\n if (self.leaves[leaf] == 0) {\\n revert LeafDoesNotExist();\\n }\\n\\n return self.leaves[leaf] - 1;\\n }\\n\\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\\n /// current tree depth.\\n /// @param self: A storage reference to the 'LeanIMTData' struct.\\n /// @return The root hash of the tree.\\n function _root(LeanIMTData storage self) internal view returns (uint256) {\\n return self.sideNodes[self.depth];\\n }\\n}\\n\",\"keccak256\":\"0x6385ce9153d11d9824163464193d4ba3dd304e662dccd365ba2fc381a359762b\",\"license\":\"MIT\"},\"contracts/Enclave.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IEnclave, E3, IE3Program } from \\\"./interfaces/IEnclave.sol\\\";\\nimport { IInputValidator } from \\\"./interfaces/IInputValidator.sol\\\";\\nimport { ICiphernodeRegistry } from \\\"./interfaces/ICiphernodeRegistry.sol\\\";\\nimport { IDecryptionVerifier } from \\\"./interfaces/IDecryptionVerifier.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {\\n InternalLeanIMT,\\n LeanIMTData,\\n PoseidonT3\\n} from \\\"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\\\";\\n\\ncontract Enclave is IEnclave, OwnableUpgradeable {\\n using InternalLeanIMT for LeanIMTData;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\\n uint256 public maxDuration; // maximum duration of a computation in seconds.\\n uint256 public nexte3Id; // ID of the next E3.\\n uint256 public requests; // total number of requests made to Enclave.\\n\\n // Mapping of allowed E3 Programs.\\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\\n\\n // Mapping of E3s.\\n mapping(uint256 e3Id => E3 e3) public e3s;\\n\\n // Mapping of input merkle trees.\\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\\n\\n // Mapping counting the number of inputs for each E3.\\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\\n\\n // Mapping of enabled encryption schemes.\\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\\n public decryptionVerifiers;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeSelectionFailed();\\n error E3ProgramNotAllowed(IE3Program e3Program);\\n error E3AlreadyActivated(uint256 e3Id);\\n error E3Expired();\\n error E3NotActivated(uint256 e3Id);\\n error E3NotReady();\\n error E3DoesNotExist(uint256 e3Id);\\n error ModuleAlreadyEnabled(address module);\\n error ModuleNotEnabled(address module);\\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\\n error InvalidComputationRequest(IInputValidator inputValidator);\\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\\n error InvalidDuration(uint256 duration);\\n error InvalidOutput(bytes output);\\n error InvalidInput();\\n error InvalidStartWindow();\\n error InvalidThreshold(uint32[2] threshold);\\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\\n error CiphertextOutputNotPublished(uint256 e3Id);\\n error PaymentRequired(uint256 value);\\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @param _owner The owner of this contract\\n /// @param _maxDuration The maximum duration of a computation in seconds\\n constructor(\\n address _owner,\\n ICiphernodeRegistry _ciphernodeRegistry,\\n uint256 _maxDuration\\n ) {\\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\\n }\\n\\n /// @param _owner The owner of this contract\\n /// @param _maxDuration The maximum duration of a computation in seconds\\n function initialize(\\n address _owner,\\n ICiphernodeRegistry _ciphernodeRegistry,\\n uint256 _maxDuration\\n ) public initializer {\\n __Ownable_init(msg.sender);\\n setMaxDuration(_maxDuration);\\n setCiphernodeRegistry(_ciphernodeRegistry);\\n if (_owner != owner()) transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function request(\\n address filter,\\n uint32[2] calldata threshold,\\n uint256[2] calldata startWindow,\\n uint256 duration,\\n IE3Program e3Program,\\n bytes memory e3ProgramParams,\\n bytes memory computeProviderParams\\n ) external payable returns (uint256 e3Id, E3 memory e3) {\\n // TODO: allow for other payment methods or only native tokens?\\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\\n require(msg.value > 0, PaymentRequired(msg.value));\\n require(\\n threshold[1] >= threshold[0] && threshold[0] > 0,\\n InvalidThreshold(threshold)\\n );\\n require(\\n // TODO: do we need a minimum start window to allow time for committee selection?\\n startWindow[1] >= startWindow[0] &&\\n startWindow[1] >= block.timestamp,\\n InvalidStartWindow()\\n );\\n require(\\n duration > 0 && duration <= maxDuration,\\n InvalidDuration(duration)\\n );\\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\\n\\n // TODO: should IDs be incremental or produced deterministically?\\n e3Id = nexte3Id;\\n nexte3Id++;\\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\\n\\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\\n encryptionSchemeId\\n ];\\n require(\\n decryptionVerifiers[encryptionSchemeId] !=\\n IDecryptionVerifier(address(0)),\\n InvalidEncryptionScheme(encryptionSchemeId)\\n );\\n require(\\n address(inputValidator) != address(0),\\n InvalidComputationRequest(inputValidator)\\n );\\n\\n e3 = E3({\\n seed: seed,\\n threshold: threshold,\\n requestBlock: block.number,\\n startWindow: startWindow,\\n duration: duration,\\n expiration: 0,\\n encryptionSchemeId: encryptionSchemeId,\\n e3Program: e3Program,\\n e3ProgramParams: e3ProgramParams,\\n inputValidator: inputValidator,\\n decryptionVerifier: decryptionVerifier,\\n committeePublicKey: hex\\\"\\\",\\n ciphertextOutput: hex\\\"\\\",\\n plaintextOutput: hex\\\"\\\"\\n });\\n e3s[e3Id] = e3;\\n\\n require(\\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\\n CommitteeSelectionFailed()\\n );\\n\\n emit E3Requested(e3Id, e3, filter, e3Program);\\n }\\n\\n function activate(\\n uint256 e3Id,\\n bytes memory publicKey\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n\\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\\n // TODO: handle what happens to the payment if the start window has passed.\\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\\n\\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\\n require(\\n keccak256(publicKey) == publicKeyHash,\\n CommitteeSelectionFailed()\\n );\\n uint256 expiresAt = block.timestamp + e3.duration;\\n e3s[e3Id].expiration = expiresAt;\\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\\n\\n emit E3Activated(e3Id, expiresAt, publicKey);\\n\\n return true;\\n }\\n\\n function publishInput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n // TODO: should we have an input window, including both a start and end timestamp?\\n require(\\n e3.expiration > block.timestamp,\\n InputDeadlinePassed(e3Id, e3.expiration)\\n );\\n\\n bytes memory input = e3.inputValidator.validate(msg.sender, data);\\n uint256 inputHash = PoseidonT3.hash(\\n [uint256(keccak256(input)), inputCounts[e3Id]]\\n );\\n\\n inputCounts[e3Id]++;\\n inputs[e3Id]._insert(inputHash);\\n success = true;\\n\\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\\n }\\n\\n function publishCiphertextOutput(\\n uint256 e3Id,\\n bytes memory ciphertextOutput,\\n bytes memory proof\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n require(\\n e3.expiration <= block.timestamp,\\n InputDeadlineNotPassed(e3Id, e3.expiration)\\n );\\n // TODO: should the output verifier be able to change its mind?\\n //i.e. should we be able to call this multiple times?\\n require(\\n e3.ciphertextOutput == bytes32(0),\\n CiphertextOutputAlreadyPublished(e3Id)\\n );\\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\\n require(success, InvalidOutput(ciphertextOutput));\\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\\n\\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\\n }\\n\\n function publishPlaintextOutput(\\n uint256 e3Id,\\n bytes memory plaintextOutput,\\n bytes memory proof\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n require(\\n e3.ciphertextOutput != bytes32(0),\\n CiphertextOutputNotPublished(e3Id)\\n );\\n require(\\n e3.plaintextOutput.length == 0,\\n PlaintextOutputAlreadyPublished(e3Id)\\n );\\n (success) = e3.decryptionVerifier.verify(\\n e3Id,\\n keccak256(plaintextOutput),\\n proof\\n );\\n require(success, InvalidOutput(plaintextOutput));\\n e3s[e3Id].plaintextOutput = plaintextOutput;\\n\\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setMaxDuration(\\n uint256 _maxDuration\\n ) public onlyOwner returns (bool success) {\\n maxDuration = _maxDuration;\\n success = true;\\n emit MaxDurationSet(_maxDuration);\\n }\\n\\n function setCiphernodeRegistry(\\n ICiphernodeRegistry _ciphernodeRegistry\\n ) public onlyOwner returns (bool success) {\\n require(\\n address(_ciphernodeRegistry) != address(0) &&\\n _ciphernodeRegistry != ciphernodeRegistry,\\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\\n );\\n ciphernodeRegistry = _ciphernodeRegistry;\\n success = true;\\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\\n }\\n\\n function enableE3Program(\\n IE3Program e3Program\\n ) public onlyOwner returns (bool success) {\\n require(\\n !e3Programs[e3Program],\\n ModuleAlreadyEnabled(address(e3Program))\\n );\\n e3Programs[e3Program] = true;\\n success = true;\\n emit E3ProgramEnabled(e3Program);\\n }\\n\\n function disableE3Program(\\n IE3Program e3Program\\n ) public onlyOwner returns (bool success) {\\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\\n delete e3Programs[e3Program];\\n success = true;\\n emit E3ProgramDisabled(e3Program);\\n }\\n\\n function setDecryptionVerifier(\\n bytes32 encryptionSchemeId,\\n IDecryptionVerifier decryptionVerifier\\n ) public onlyOwner returns (bool success) {\\n require(\\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\\n InvalidEncryptionScheme(encryptionSchemeId)\\n );\\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\\n success = true;\\n emit EncryptionSchemeEnabled(encryptionSchemeId);\\n }\\n\\n function disableEncryptionScheme(\\n bytes32 encryptionSchemeId\\n ) public onlyOwner returns (bool success) {\\n require(\\n decryptionVerifiers[encryptionSchemeId] !=\\n IDecryptionVerifier(address(0)),\\n InvalidEncryptionScheme(encryptionSchemeId)\\n );\\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\\n address(0)\\n );\\n success = true;\\n emit EncryptionSchemeDisabled(encryptionSchemeId);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\\n e3 = e3s[e3Id];\\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\\n }\\n\\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\\n require(\\n e3s[e3Id].e3Program != IE3Program(address(0)),\\n E3DoesNotExist(e3Id)\\n );\\n return InternalLeanIMT._root(inputs[e3Id]);\\n }\\n\\n function getDecryptionVerifier(\\n bytes32 encryptionSchemeId\\n ) public view returns (IDecryptionVerifier) {\\n return decryptionVerifiers[encryptionSchemeId];\\n }\\n}\\n\",\"keccak256\":\"0x192cc4c3a9744ee4eb0fc6a30019367b6fba8eaba26bf613735fbcac6e63a7ff\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/ICiphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface ICiphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeAdded(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeRemoved(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n function isCiphernodeEligible(address ciphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The hash of the public key generated by the given committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKeyHash The hash of the public key of the given committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes32 publicKeyHash);\\n}\\n\",\"keccak256\":\"0xe24e6322e8c6fc83461edfbdbedb409e243f1c4e79021a74585cfe875c225aa2\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IDecryptionVerifier.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IDecryptionVerifier {\\n /// @notice This function should be called by the Enclave contract to verify the\\n /// decryption of output of a computation.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\\n /// @param proof ABI encoded proof of the given output hash.\\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\\n function verify(\\n uint256 e3Id,\\n bytes32 plaintextOutputHash,\\n bytes memory proof\\n ) external view returns (bool success);\\n}\\n\",\"keccak256\":\"0xb92991a581d3c18cdc273497687ec1c6e3016674314f21fe56917aece5d10863\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IE3.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IInputValidator } from \\\"./IInputValidator.sol\\\";\\nimport { IE3Program } from \\\"./IE3Program.sol\\\";\\nimport { IDecryptionVerifier } from \\\"./IDecryptionVerifier.sol\\\";\\n\\n/// @title E3 struct\\n/// @notice This struct represents an E3 computation.\\n/// @param threshold M/N threshold for the committee.\\n/// @param requestBlock Block number when the E3 was requested.\\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\\n/// @param duration Duration of the E3.\\n/// @param expiration Timestamp when committee duties expire.\\n/// @param e3Program Address of the E3 Program contract.\\n/// @param computeProvider Address of the compute provider contract.\\n/// @param inputValidator Address of the input validator contract.\\n/// @param decryptionVerifier Address of the output verifier contract.\\n/// @param committeeId ID of the selected committee.\\n/// @param ciphertextOutput Encrypted output data.\\n/// @param plaintextOutput Decrypted output data.\\nstruct E3 {\\n uint256 seed;\\n uint32[2] threshold;\\n uint256 requestBlock;\\n uint256[2] startWindow;\\n uint256 duration;\\n uint256 expiration;\\n bytes32 encryptionSchemeId;\\n IE3Program e3Program;\\n bytes e3ProgramParams;\\n IInputValidator inputValidator;\\n IDecryptionVerifier decryptionVerifier;\\n bytes32 committeePublicKey;\\n bytes32 ciphertextOutput;\\n bytes plaintextOutput;\\n}\\n\",\"keccak256\":\"0x16f12d3e46b12fcbff721eb8c358324fd400c95b40d57ed06b05e7afd590811e\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IE3Program.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IInputValidator } from \\\"./IInputValidator.sol\\\";\\n\\ninterface IE3Program {\\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\\n /// @param e3Id ID of the E3.\\n /// @param seed Seed for the computation.\\n /// @param e3ProgramParams ABI encoded computation parameters.\\n /// @param computeProviderParams ABI encoded compute provider parameters.\\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\\n /// @return inputValidator The input validator to be used for the computation.\\n function validate(\\n uint256 e3Id,\\n uint256 seed,\\n bytes calldata e3ProgramParams,\\n bytes calldata computeProviderParams\\n )\\n external\\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\\n\\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\\n /// @param e3Id ID of the E3.\\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\\n /// @return success Whether the output data is valid.\\n function verify(\\n uint256 e3Id,\\n bytes32 ciphertextOutputHash,\\n bytes memory proof\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0xd60e92b5b6498daf0b7f1238d354156c67d25c03caaaabbc601368e9e4a295b2\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IEnclave.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { E3, IE3Program } from \\\"./IE3.sol\\\";\\n\\ninterface IEnclave {\\n ////////////////////////////////////////////////////////////\\n // //\\n // Events //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\\n /// @param e3Id ID of the E3.\\n /// @param e3 Details of the E3.\\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\\n /// @param e3Program Address of the Computation module selected.\\n event E3Requested(\\n uint256 e3Id,\\n E3 e3,\\n address filter,\\n IE3Program indexed e3Program\\n );\\n\\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\\n /// @param e3Id ID of the E3.\\n /// @param expiration Timestamp when committee duties expire.\\n /// @param committeePublicKey Public key of the committee.\\n event E3Activated(\\n uint256 e3Id,\\n uint256 expiration,\\n bytes committeePublicKey\\n );\\n\\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\\n /// successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded input data.\\n event InputPublished(\\n uint256 indexed e3Id,\\n bytes data,\\n uint256 inputHash,\\n uint256 index\\n );\\n\\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\\n /// is successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutput ABI encoded plaintext output.\\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\\n\\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\\n /// is successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param ciphertextOutput ABI encoded ciphertext output.\\n event CiphertextOutputPublished(\\n uint256 indexed e3Id,\\n bytes ciphertextOutput\\n );\\n\\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\\n /// @param maxDuration The maximum duration of a computation in seconds.\\n event MaxDurationSet(uint256 maxDuration);\\n\\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\\n event CiphernodeRegistrySet(address ciphernodeRegistry);\\n\\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\\n\\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\\n\\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\\n /// @param e3Program The address of the E3 Program.\\n event E3ProgramEnabled(IE3Program e3Program);\\n\\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\\n /// @param e3Program The address of the E3 Program.\\n event E3ProgramDisabled(IE3Program e3Program);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\\n /// @dev This function MUST emit the E3Requested event.\\n /// @param filter IDs of the pool of nodes from which to select the committee.\\n /// @param threshold The M/N threshold for the committee.\\n /// @param duration The duration of the computation in seconds.\\n /// @param e3Program Address of the E3 Program.\\n /// @param e3ProgramParams ABI encoded computation parameters.\\n /// @param computeProviderParams ABI encoded compute provider parameters.\\n /// @return e3Id ID of the E3.\\n /// @return e3 The E3 struct.\\n function request(\\n address filter,\\n uint32[2] calldata threshold,\\n uint256[2] calldata startWindow,\\n uint256 duration,\\n IE3Program e3Program,\\n bytes memory e3ProgramParams,\\n bytes memory computeProviderParams\\n ) external payable returns (uint256 e3Id, E3 memory e3);\\n\\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\\n /// initialized and is ready for input.\\n /// @dev This function MUST emit the E3Activated event.\\n /// @dev This function MUST revert if the given E3 has not yet been requested.\\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\\n /// @param e3Id ID of the E3.\\n /// @param publicKey Public key of the committee.\\n /// @return success True if the E3 was successfully activated.\\n function activate(\\n uint256 e3Id,\\n bytes memory publicKey\\n ) external returns (bool success);\\n\\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the E3 is not yet activated.\\n /// @dev This function MUST emit the InputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded input data to publish.\\n /// @return success True if the input was successfully published.\\n function publishInput(\\n uint256 e3Id,\\n bytes calldata data\\n ) external returns (bool success);\\n\\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\\n /// @dev This function MUST emit the CiphertextOutputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param ciphertextOutput ABI encoded output data to verify.\\n /// @param proof ABI encoded data to verify the ciphertextOutput.\\n /// @return success True if the output was successfully published.\\n function publishCiphertextOutput(\\n uint256 e3Id,\\n bytes memory ciphertextOutput,\\n bytes memory proof\\n ) external returns (bool success);\\n\\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the output has not been published.\\n /// @dev This function MUST emit the PlaintextOutputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutput ABI encoded plaintext output.\\n /// @param proof ABI encoded data to verify the plaintextOutput.\\n function publishPlaintextOutput(\\n uint256 e3Id,\\n bytes memory plaintextOutput,\\n bytes memory proof\\n ) external returns (bool success);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to set the maximum duration of requested computations.\\n /// @param _maxDuration The maximum duration of a computation in seconds.\\n /// @return success True if the max duration was successfully set.\\n function setMaxDuration(\\n uint256 _maxDuration\\n ) external returns (bool success);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the E3 does not exist.\\n /// @param e3Id ID of the E3.\\n /// @return e3 The struct representing the requested E3.\\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\\n\\n /// @notice This function returns root of the input merkle tree for a given E3.\\n /// @dev This function MUST revert if the E3 does not exist.\\n /// @param e3Id ID of the E3.\\n /// @return root The root of the input merkle tree.\\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\\n}\\n\",\"keccak256\":\"0xb1c9cd24aeb1dbf988555945ae532860c8a60a874f19020e48e29c9e3e5ebb64\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IInputValidator.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IInputValidator {\\n /// @notice This function should be called by the Enclave contract to validate the\\n /// input of a computation.\\n /// @param sender The account that is submitting the input.\\n /// @param data The input to be verified.\\n /// @return input The decoded, policy-approved application payload.\\n function validate(\\n address sender,\\n bytes memory data\\n ) external returns (bytes memory input);\\n}\\n\",\"keccak256\":\"0x20d4016bd59c317c5571cfe6c3e8f46cbabddc0b926dc64019eeae8d29788653\",\"license\":\"LGPL-3.0-only\"},\"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": "0x6080346102a457601f61284438819003918201601f19168301916001600160401b038311848410176102a9578084926060946040528339810103126102a45780516001600160a01b0381168082036102a45760208301516001600160a01b03811693908490036102a457604090810151600080516020612824833981519152549182901c60ff161594916001600160401b0381168015908161029c575b6001149081610292575b159081610289575b50610278576001600160401b03198116600117600080516020612824833981519152557fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916020918761024d575b50610105610335565b61010d610335565b610116336102bf565b61011e610363565b80600155604051908152a1610131610363565b80151580610238575b1561022457600080546001600160a01b031916821790556040519081527f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b690602090a1600080516020612804833981519152546001600160a01b03160361020d575b506101b1575b60405161246a908161039a8239f35b68ff0000000000000000196000805160206128248339815191525416600080516020612824833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a16101a2565b61021e90610219610363565b6102bf565b3861019c565b6375ac4eb760e11b60005260045260246000fd5b506000546001600160a01b031681141561013a565b6001600160481b031916680100000000000000011760008051602061282483398151915255386100fc565b63f92ee8a960e01b60005260046000fd5b905015386100ae565b303b1591506100a6565b87915061009c565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0316801561031f5760008051602061280483398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff6000805160206128248339815191525460401c161561035257565b631afcd79f60e31b60005260046000fd5b600080516020612804833981519152546001600160a01b0316330361038457565b63118cdaa760e01b6000523360045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c80630e092fc314611b3e5780630ef81b2f14611b0957806310bc628114611b095780631794bb3c146118e35780634017daf0146117f6578063406ed35c146117c35780634e92ec63146117355780634fc77264146116955780635314e9fa1461150d5780636db5c8fd146114ef578063715018a6146114565780637edcd7ab146111fd5780638da5cb5b146111b75780638dcdd86b1461119057806393b58f861461099b5780639c8570c814610828578063b3c88d67146107fc578063b74cb2db146107de578063c4ccafa21461079f578063cb64961714610781578063cbd16872146106c8578063cf0f34c4146106aa578063d016b08d14610279578063ddef9ea114610244578063f2fde38b14610219578063fad8e111146101ec5763fd2f3d011461014557600080fd5b346101e75760203660031901126101e7576001600160a01b03610166611ba3565b61016e6123d5565b1680600052600460205260ff604060002054166101d3576020817fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46792600052600482526040600020600160ff19825416179055604051908152a1602060405160018152f35b63b29d459560e01b60005260045260246000fd5b600080fd5b346101e75760203660031901126101e757602061020f61020a611ba3565b61234a565b6040519015158152f35b346101e75760203660031901126101e757610242610235611ba3565b61023d6123d5565b6122a4565b005b346101e75760203660031901126101e75760043560005260066020526040806000206001815491015482519182526020820152f35b346101e75761028736611ebe565b61029082611fe8565b60a081016102a18482511515612138565b514281111561069257506102ec6000926001600160a01b0361012085940151169060405194858094819363caf9278560e01b8352336004840152604060248401526044830190611d15565b03925af180156105915760009061060d575b61035a9150733333333C0A88F9BE4fd23ed0536F9B6c427e3B93602060405161032681611c10565b835182850120815285600052600782526040600020548282015260405180958192632b0aac7f60e11b835260048301612276565b0381845af4928315610591576000936105d9575b508360005260076020526040600020610387815461222b565b905560008481526006602052604090207f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184106103cf576361c0541760e11b60005260046000fd5b836103e5576314b48df160e11b60005260046000fd5b83600052600381016020526040600020546105c857805491600182019283549360ff85116104d257600182018083116104d2576001861b106105b8575b84905585916000905b8582106104e8575050906104416003939261222b565b938483556000526002820160205260406000205584600052016020526040600020558260005260076020526040600020549060001982019182116104d2577f7555a0b1b87fe36304326aed23f5c78102b63922b1141f8df7d4593eff2021dd926104b992604051938493606085526060850190611d15565b91602084015260408301520390a2602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b909260018084861c161460001461059d57602061053c916040519061050c82611c10565b8660005260028801835260406000205482528282015260405180938192632b0aac7f60e11b835260048301612276565b0381855af480156105915760009061055c575b60019150935b019061042b565b6020823d8211610589575b8161057460209383611c2c565b8101031261058657506001905161054f565b80fd5b3d9150610567565b6040513d6000823e3d90fd5b92806001916000526002860160205284604060002055610555565b936105c29061222b565b93610422565b6312c50cad60e11b60005260046000fd5b90926020823d602011610605575b816105f460209383611c2c565b81010312610586575051918461036e565b3d91506105e7565b3d8082843e61061c8184611c2c565b82019160208184031261068a5780519067ffffffffffffffff821161068e570182601f8201121561068a5780519161065383611e5b565b936106616040519586611c2c565b83855260208484010111610586575082916106859160208061035a96019101611cf2565b6102fe565b5080fd5b8280fd5b8363142c294360e31b60005260045260245260446000fd5b346101e75760203660031901126101e757602061020f60043561223a565b346101e75760403660031901126101e7576004356024356001600160a01b0381168091036101e7577ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb699160209161071d6123d5565b801515828161075f575b6107309161211c565b81600052600883526040600020906001600160a01b0319825416179055604051908152a1602060405160018152f35b60009081526008855260409020546001600160a01b0316821415905082610727565b346101e75760003660031901126101e7576020600254604051908152f35b346101e75760203660031901126101e7576001600160a01b036107c0611ba3565b166000526004602052602060ff604060002054166040519015158152f35b346101e75760003660031901126101e7576020600354604051908152f35b346101e75760203660031901126101e75760043560005260076020526020604060002054604051908152f35b346101e75761083636611eee565b9161084081611fe8565b9160a083016108528382511515612138565b51428111610983575061018083015161096e5760206108a06000956001600160a01b0360e08551858701209701511690604051978880948193632f0e1bbf60e01b83528a8a6004850161216c565b03925af192831561059157602094600094610917575b508161090a916108e77f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0719487612188565b8460005260058752600d6040600020015560405191829187835287830190611d15565b0390a26040519015158152f35b61090a9194509161095e7f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade07193873d8911610967575b6109568183611c2c565b810190612154565b949150916108b6565b503d61094c565b50637eb9cea960e11b60005260045260246000fd5b826370c05fb960e11b60005260045260245260446000fd5b6101203660031901126101e7576109b0611ba3565b366064116101e7573660a4116101e75760a43560c435916001600160a01b03831683036101e75760e43567ffffffffffffffff81116101e7576109f7903690600401611e77565b906101043567ffffffffffffffff81116101e757610a19903690600401611e77565b90610a22611f59565b50341561117b5760443563ffffffff8116908181036101e7575063ffffffff610a496121d0565b16111580611165575b1561114757608435606435811015908161113c575b501561112b578315158061111f575b1561110a576001600160a01b038516600052600460205260ff60406000205416156110ec57610b149060025493610aac8561222b565b6002556040805160208101904482528783820152828152610ace606082611c2c565b5190209481518095819263530ebf1f60e11b835289600484015288602484015260806044840152610b026084840187611d15565b83810360031901606485015290611d15565b038160006001600160a01b038c165af190811561059157600093849261109b575b506000848152600860205260409020546001600160a01b0390811692610b5d8685151561211c565b169081156110865760405195610b7287611bf3565b8652604094855198610b84878b611c2c565b6000996024815b6064821061106e575050602089015243878901528651610bab8882611c2c565b6064815b60a4821061105e575050606089015260808801528860a088015260c08701526001600160a01b03891660e087015261010086015261012085015261014084015284610160840152846101808401526020948251610c0c8782611c2c565b8181526101a0850152848152600586528281208451815560208501518290835b89600282106110365750505060018201558385015160028201556060850151825b600281106110215750506080850151600582015560a0850151600682015560c085015160078201556001600160a01b0360e0860151166001600160a01b036008830191166001600160a01b031982541617905561010085015180519067ffffffffffffffff8211610f6257610cc56009840154611bb9565b601f8111610ff0575b508890601f8311600114610f8157600e939291859183610f76575b50508160011b916000199060031b1c19161760098201555b6001600160a01b03610120870151166001600160a01b03600a830191166001600160a01b03198254161790556001600160a01b03610140870151166001600160a01b03600b830191166001600160a01b0319825416179055610160860151600c820155610180860151600d820155016101a085015180519067ffffffffffffffff8211610f62578190610d948454611bb9565b601f8111610f29575b508990601f8311600114610ec6578592610ebb575b50508160011b916000199060031b1c19161790555b80866001600160a01b036084818454169587519485938492639ccb58d560e01b84528c60048501521697886024840152610e03604484016121f4565b5af1908115610eb1578291610e94575b5015610e8557507fe31ba2ed37bce9c2bca28aabe3990572a1694b7a208f61e5cced4471fa33c8e56001600160a01b03610e81959697845191829189835260608b840152610e646060840189611d3a565b958784015216930390a28080519586958652850152830190611d3a565b0390f35b630d8dbe2560e01b8152600490fd5b610eab9150873d8911610967576109568183611c2c565b88610e13565b84513d84823e3d90fd5b015190508a80610db2565b8486528a86209250601f198416865b8c828210610f13575050908460019594939210610efa575b505050811b019055610dc7565b015160001960f88460031b161c191690558a8080610eed565b6001859682939686015181550195019301610ed5565b610f52908587528b8720601f850160051c8101918d8610610f58575b601f0160051c01906121b9565b8b610d9d565b9091508190610f45565b634e487b7160e01b84526041600452602484fd5b015190508b80610ce9565b9060098401855289852091855b8b601f1986168210610fda575050918391600193600e9695601f19811610610fc1575b505050811b016009820155610d01565b015160001960f88460031b161c191690558b8080610fb1565b6001849582939585015181550194019201610f8e565b61101b906009850186528a8620601f850160051c8101918c8610610f5857601f0160051c01906121b9565b8a610cce565b81518382016003015590880190600101610c4d565b829363ffffffff6001939451169063ffffffff8560051b92831b921b19161793019101610c2c565b8135815260209182019101610baf565b6020809161107b846121e3565b815201910190610b8b565b50633ca1cee360e11b60005260045260246000fd5b9091506040813d6040116110e4575b816110b760409383611c2c565b810103126110e05760208151910151936001600160a01b03851685036105865750929088610b35565b8380fd5b3d91506110aa565b6001600160a01b038563295a6a6f60e11b6000521660045260246000fd5b836313b783af60e21b60005260045260246000fd5b50600154841115610a76565b6308594fb760e01b60005260046000fd5b905042111586610a67565b604051633744092160e21b8152604490611163600482016121f4565bfd5b5063ffffffff6111736121d0565b161515610a52565b638c4fcd9360e01b6000523460045260246000fd5b346101e75760003660031901126101e75760206001600160a01b0360005416604051908152f35b346101e75760003660031901126101e75760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101e75761120b36611eee565b611216839293611fe8565b6112268360a08301511515612138565b61018081015115611441576101a08101515161142c5761127592916001600160a01b03610140602093015116855183870120604051809681948293632f0e1bbf60e01b8452886004850161216c565b03915afa9182156105915760009261140b575b506112938383612188565b806000526005602052600e6040600020019280519367ffffffffffffffff85116113f5576020946112c48254611bb9565b601f81116113c5575b5085601f821160011461133c5791817f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169949261090a94600091611331575b508160011b916000199060031b1c19161790555b60405191829187835287830190611d15565b90508301518961130b565b601f1982169083600052806000209160005b8181106113ae57509261090a9492600192827f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169989610611395575b5050811b01905561131f565b85015160001960f88460031b161c191690558980611389565b91928960018192868a01518155019401920161134e565b6113ef908360005287600020601f840160051c810191898510610f5857601f0160051c01906121b9565b866112cd565b634e487b7160e01b600052604160045260246000fd5b61142591925060203d602011610967576109568183611c2c565b9083611288565b826360ec327960e01b60005260045260246000fd5b8263032c20ef60e21b60005260045260246000fd5b346101e75760003660031901126101e75761146f6123d5565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346101e75760003660031901126101e7576020600154604051908152f35b346101e75761151b36611ebe565b9061152581611fe8565b9060a08201516116815760608201805151421061167057602042915101511061165f5760249160206001600160a01b036000541660405194858092630e82f3b760e41b82528660048301525afa9283156105915760009361162b575b50835192602085019384200361161a57608001514201918242116104d2577f50df9e2c9fc5a7f4a07e403fa0300b88fcc8c6943bdff4b8ae71f55b7fd95f899361160c918360005260056020528460066040600020015581519020836000526005602052600c6040600020015560405193849384526020840152606060408401526060830190611d15565b0390a1602060405160018152f35b630d8dbe2560e01b60005260046000fd5b9092506020813d602011611657575b8161164760209383611c2c565b810103126101e757519184611581565b3d915061163a565b633d82a7cd60e11b60005260046000fd5b63a0750b5160e01b60005260046000fd5b633e26347b60e21b60005260045260246000fd5b346101e75760203660031901126101e7576001600160a01b036116b6611ba3565b6116be6123d5565b1680600052600460205260ff6040600020541615611721576020817f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e79260005260048252604060002060ff198154169055604051908152a1602060405160018152f35b6321ac7c5f60e01b60005260045260246000fd5b346101e75760203660031901126101e7577f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc60206004356117746123d5565b8060005260088252611796816001600160a01b0360406000205416151561211c565b806000526008825260406000206001600160a01b03198154169055604051908152a1602060405160018152f35b346101e75760203660031901126101e757610e816117e2600435611fe8565b604051918291602083526020830190611d3a565b346101e75760203660031901126101e757600435600052600560205260206040600020610e8181549160028101546005820154916006810154926007820154936118bd6001600160a01b0360088501541661185360098601611c4e565b906001600160a01b03600a87015416976001600160a01b03600b8801541694600c88015496611889600e600d8b01549a01611c4e565b996040519e8f9e8f908152015260408d015260608c015260808b015260a08a015261018060c08a0152610180890190611d15565b9460e0880152610100870152610120860152610140850152838203610160850152611d15565b346101e75760603660031901126101e7576118fc611ba3565b602435906001600160a01b03821682036101e7577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff821680159081611b01575b6001149081611af7575b159081611aee575b50611add5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556119cc9184611a9e575b506119aa61241d565b6119b261241d565b6119bb336122a4565b6119c660443561223a565b5061234a565b506001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b03821603611a8c575b50611a0f57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b611a989061023d6123d5565b81611a08565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055846119a1565b63f92ee8a960e01b60005260046000fd5b90501585611961565b303b159150611959565b85915061194f565b346101e75760203660031901126101e757600435600052600860205260206001600160a01b0360406000205416604051908152f35b346101e75760203660031901126101e757600435806000526005602052611b78816001600160a01b03600860406000200154161515611f3d565b6000526006602052600260406000206001810154600052016020526020604060002054604051908152f35b600435906001600160a01b03821682036101e757565b90600182811c92168015611be9575b6020831014611bd357565b634e487b7160e01b600052602260045260246000fd5b91607f1691611bc8565b6101c0810190811067ffffffffffffffff8211176113f557604052565b6040810190811067ffffffffffffffff8211176113f557604052565b90601f8019910116810190811067ffffffffffffffff8211176113f557604052565b9060405191826000825492611c6284611bb9565b8084529360018116908115611cd05750600114611c89575b50611c8792500383611c2c565b565b90506000929192526020600020906000915b818310611cb4575050906020611c879282010138611c7a565b6020919350806001915483858901015201910190918492611c9b565b905060209250611c8794915060ff191682840152151560051b82010138611c7a565b60005b838110611d055750506000910152565b8181015183820152602001611cf5565b90602091611d2e81518092818552858086019101611cf2565b601f01601f1916010190565b919091805183526020810151602084016000905b60028210611e3f5750505060408101516060840152606081015192608081016000905b60028210611e29575050611e26929350608082015160c082015260a082015160e082015260c08201516101008201526001600160a01b0360e0830151166101208201526101a0611dd4610100840151610200610140850152610200840190611d15565b926001600160a01b03610120820151166101608401526001600160a01b0361014082015116610180840152610160810151828401526101808101516101c08401520151906101e0818403910152611d15565b90565b6020806001928851815201960191019094611d71565b60208060019263ffffffff865116815201930191019091611d4e565b67ffffffffffffffff81116113f557601f01601f191660200190565b81601f820112156101e757803590611e8e82611e5b565b92611e9c6040519485611c2c565b828452602083830101116101e757816000926020809301838601378301015290565b9060406003198301126101e757600435916024359067ffffffffffffffff82116101e757611e2691600401611e77565b60606003198201126101e7576004359160243567ffffffffffffffff81116101e75782611f1d91600401611e77565b916044359067ffffffffffffffff82116101e757611e2691600401611e77565b15611f455750565b63cd6f4a4f60e01b60005260045260246000fd5b60405190611f6682611bf3565b60606101a0836000815260408051611f7e8282611c2c565b813682376020830152600081830152805190611f9a8183611c2c565b3682378382015260006080820152600060a0820152600060c0820152600060e08201528261010082015260006101208201526000610140820152600061016082015260006101808201520152565b90611ff1611f59565b5081600052600560205260406000209160405161200d81611bf3565b8354815260405163ffffffff6001860154818116835260201c166020820152612037604082611c2c565b6020820152600284015460408201526040518060038601906000905b6002821061210657505050611c8792918161207760406001600160a01b0394611c2c565b606082015260058601546080820152600686015460a0820152600786015460c08201526120f6600e836008890154169760e084019889526120ba60098201611c4e565b61010085015284600a8201541661012085015284600b82015416610140850152600c810154610160850152600d81015461018085015201611c4e565b6101a08201529451161515611f3d565b6001602081928554815201930191019091612053565b156121245750565b6381c4951960e01b60005260045260246000fd5b156121405750565b63166b4d0360e01b60005260045260246000fd5b908160209103126101e7575180151581036101e75790565b611e269392606092825260208201528160408201520190611d15565b156121905750565b604051632f9f8ab960e01b8152602060048201529081906121b5906024830190611d15565b0390fd5b8181106121c4575050565b600081556001016121b9565b60243563ffffffff811681036101e75790565b359063ffffffff821682036101e757565b6024906000905b6002821061220857505050565b60208060019263ffffffff61221c876121e3565b168152019301910190916121fb565b60001981146104d25760010190565b60207fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916122666123d5565b80600155604051908152a1600190565b919060408301926000905b6002821061228e57505050565b6020806001928551815201930191019091612281565b6001600160a01b03168015612334576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b039061235b6123d5565b16801515806123c0575b156123ac576020817f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b6926001600160a01b03196000541617600055604051908152a1600190565b6375ac4eb760e11b60005260045260246000fd5b506001600160a01b0360005416811415612365565b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361240857565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561244c57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081b000a9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", - "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c80630e092fc314611b3e5780630ef81b2f14611b0957806310bc628114611b095780631794bb3c146118e35780634017daf0146117f6578063406ed35c146117c35780634e92ec63146117355780634fc77264146116955780635314e9fa1461150d5780636db5c8fd146114ef578063715018a6146114565780637edcd7ab146111fd5780638da5cb5b146111b75780638dcdd86b1461119057806393b58f861461099b5780639c8570c814610828578063b3c88d67146107fc578063b74cb2db146107de578063c4ccafa21461079f578063cb64961714610781578063cbd16872146106c8578063cf0f34c4146106aa578063d016b08d14610279578063ddef9ea114610244578063f2fde38b14610219578063fad8e111146101ec5763fd2f3d011461014557600080fd5b346101e75760203660031901126101e7576001600160a01b03610166611ba3565b61016e6123d5565b1680600052600460205260ff604060002054166101d3576020817fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46792600052600482526040600020600160ff19825416179055604051908152a1602060405160018152f35b63b29d459560e01b60005260045260246000fd5b600080fd5b346101e75760203660031901126101e757602061020f61020a611ba3565b61234a565b6040519015158152f35b346101e75760203660031901126101e757610242610235611ba3565b61023d6123d5565b6122a4565b005b346101e75760203660031901126101e75760043560005260066020526040806000206001815491015482519182526020820152f35b346101e75761028736611ebe565b61029082611fe8565b60a081016102a18482511515612138565b514281111561069257506102ec6000926001600160a01b0361012085940151169060405194858094819363caf9278560e01b8352336004840152604060248401526044830190611d15565b03925af180156105915760009061060d575b61035a915073__$75f79a42d9bcbdbb69ad79ebd80f556f39$__602060405161032681611c10565b835182850120815285600052600782526040600020548282015260405180958192632b0aac7f60e11b835260048301612276565b0381845af4928315610591576000936105d9575b508360005260076020526040600020610387815461222b565b905560008481526006602052604090207f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184106103cf576361c0541760e11b60005260046000fd5b836103e5576314b48df160e11b60005260046000fd5b83600052600381016020526040600020546105c857805491600182019283549360ff85116104d257600182018083116104d2576001861b106105b8575b84905585916000905b8582106104e8575050906104416003939261222b565b938483556000526002820160205260406000205584600052016020526040600020558260005260076020526040600020549060001982019182116104d2577f7555a0b1b87fe36304326aed23f5c78102b63922b1141f8df7d4593eff2021dd926104b992604051938493606085526060850190611d15565b91602084015260408301520390a2602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b909260018084861c161460001461059d57602061053c916040519061050c82611c10565b8660005260028801835260406000205482528282015260405180938192632b0aac7f60e11b835260048301612276565b0381855af480156105915760009061055c575b60019150935b019061042b565b6020823d8211610589575b8161057460209383611c2c565b8101031261058657506001905161054f565b80fd5b3d9150610567565b6040513d6000823e3d90fd5b92806001916000526002860160205284604060002055610555565b936105c29061222b565b93610422565b6312c50cad60e11b60005260046000fd5b90926020823d602011610605575b816105f460209383611c2c565b81010312610586575051918461036e565b3d91506105e7565b3d8082843e61061c8184611c2c565b82019160208184031261068a5780519067ffffffffffffffff821161068e570182601f8201121561068a5780519161065383611e5b565b936106616040519586611c2c565b83855260208484010111610586575082916106859160208061035a96019101611cf2565b6102fe565b5080fd5b8280fd5b8363142c294360e31b60005260045260245260446000fd5b346101e75760203660031901126101e757602061020f60043561223a565b346101e75760403660031901126101e7576004356024356001600160a01b0381168091036101e7577ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb699160209161071d6123d5565b801515828161075f575b6107309161211c565b81600052600883526040600020906001600160a01b0319825416179055604051908152a1602060405160018152f35b60009081526008855260409020546001600160a01b0316821415905082610727565b346101e75760003660031901126101e7576020600254604051908152f35b346101e75760203660031901126101e7576001600160a01b036107c0611ba3565b166000526004602052602060ff604060002054166040519015158152f35b346101e75760003660031901126101e7576020600354604051908152f35b346101e75760203660031901126101e75760043560005260076020526020604060002054604051908152f35b346101e75761083636611eee565b9161084081611fe8565b9160a083016108528382511515612138565b51428111610983575061018083015161096e5760206108a06000956001600160a01b0360e08551858701209701511690604051978880948193632f0e1bbf60e01b83528a8a6004850161216c565b03925af192831561059157602094600094610917575b508161090a916108e77f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0719487612188565b8460005260058752600d6040600020015560405191829187835287830190611d15565b0390a26040519015158152f35b61090a9194509161095e7f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade07193873d8911610967575b6109568183611c2c565b810190612154565b949150916108b6565b503d61094c565b50637eb9cea960e11b60005260045260246000fd5b826370c05fb960e11b60005260045260245260446000fd5b6101203660031901126101e7576109b0611ba3565b366064116101e7573660a4116101e75760a43560c435916001600160a01b03831683036101e75760e43567ffffffffffffffff81116101e7576109f7903690600401611e77565b906101043567ffffffffffffffff81116101e757610a19903690600401611e77565b90610a22611f59565b50341561117b5760443563ffffffff8116908181036101e7575063ffffffff610a496121d0565b16111580611165575b1561114757608435606435811015908161113c575b501561112b578315158061111f575b1561110a576001600160a01b038516600052600460205260ff60406000205416156110ec57610b149060025493610aac8561222b565b6002556040805160208101904482528783820152828152610ace606082611c2c565b5190209481518095819263530ebf1f60e11b835289600484015288602484015260806044840152610b026084840187611d15565b83810360031901606485015290611d15565b038160006001600160a01b038c165af190811561059157600093849261109b575b506000848152600860205260409020546001600160a01b0390811692610b5d8685151561211c565b169081156110865760405195610b7287611bf3565b8652604094855198610b84878b611c2c565b6000996024815b6064821061106e575050602089015243878901528651610bab8882611c2c565b6064815b60a4821061105e575050606089015260808801528860a088015260c08701526001600160a01b03891660e087015261010086015261012085015261014084015284610160840152846101808401526020948251610c0c8782611c2c565b8181526101a0850152848152600586528281208451815560208501518290835b89600282106110365750505060018201558385015160028201556060850151825b600281106110215750506080850151600582015560a0850151600682015560c085015160078201556001600160a01b0360e0860151166001600160a01b036008830191166001600160a01b031982541617905561010085015180519067ffffffffffffffff8211610f6257610cc56009840154611bb9565b601f8111610ff0575b508890601f8311600114610f8157600e939291859183610f76575b50508160011b916000199060031b1c19161760098201555b6001600160a01b03610120870151166001600160a01b03600a830191166001600160a01b03198254161790556001600160a01b03610140870151166001600160a01b03600b830191166001600160a01b0319825416179055610160860151600c820155610180860151600d820155016101a085015180519067ffffffffffffffff8211610f62578190610d948454611bb9565b601f8111610f29575b508990601f8311600114610ec6578592610ebb575b50508160011b916000199060031b1c19161790555b80866001600160a01b036084818454169587519485938492639ccb58d560e01b84528c60048501521697886024840152610e03604484016121f4565b5af1908115610eb1578291610e94575b5015610e8557507fe31ba2ed37bce9c2bca28aabe3990572a1694b7a208f61e5cced4471fa33c8e56001600160a01b03610e81959697845191829189835260608b840152610e646060840189611d3a565b958784015216930390a28080519586958652850152830190611d3a565b0390f35b630d8dbe2560e01b8152600490fd5b610eab9150873d8911610967576109568183611c2c565b88610e13565b84513d84823e3d90fd5b015190508a80610db2565b8486528a86209250601f198416865b8c828210610f13575050908460019594939210610efa575b505050811b019055610dc7565b015160001960f88460031b161c191690558a8080610eed565b6001859682939686015181550195019301610ed5565b610f52908587528b8720601f850160051c8101918d8610610f58575b601f0160051c01906121b9565b8b610d9d565b9091508190610f45565b634e487b7160e01b84526041600452602484fd5b015190508b80610ce9565b9060098401855289852091855b8b601f1986168210610fda575050918391600193600e9695601f19811610610fc1575b505050811b016009820155610d01565b015160001960f88460031b161c191690558b8080610fb1565b6001849582939585015181550194019201610f8e565b61101b906009850186528a8620601f850160051c8101918c8610610f5857601f0160051c01906121b9565b8a610cce565b81518382016003015590880190600101610c4d565b829363ffffffff6001939451169063ffffffff8560051b92831b921b19161793019101610c2c565b8135815260209182019101610baf565b6020809161107b846121e3565b815201910190610b8b565b50633ca1cee360e11b60005260045260246000fd5b9091506040813d6040116110e4575b816110b760409383611c2c565b810103126110e05760208151910151936001600160a01b03851685036105865750929088610b35565b8380fd5b3d91506110aa565b6001600160a01b038563295a6a6f60e11b6000521660045260246000fd5b836313b783af60e21b60005260045260246000fd5b50600154841115610a76565b6308594fb760e01b60005260046000fd5b905042111586610a67565b604051633744092160e21b8152604490611163600482016121f4565bfd5b5063ffffffff6111736121d0565b161515610a52565b638c4fcd9360e01b6000523460045260246000fd5b346101e75760003660031901126101e75760206001600160a01b0360005416604051908152f35b346101e75760003660031901126101e75760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101e75761120b36611eee565b611216839293611fe8565b6112268360a08301511515612138565b61018081015115611441576101a08101515161142c5761127592916001600160a01b03610140602093015116855183870120604051809681948293632f0e1bbf60e01b8452886004850161216c565b03915afa9182156105915760009261140b575b506112938383612188565b806000526005602052600e6040600020019280519367ffffffffffffffff85116113f5576020946112c48254611bb9565b601f81116113c5575b5085601f821160011461133c5791817f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169949261090a94600091611331575b508160011b916000199060031b1c19161790555b60405191829187835287830190611d15565b90508301518961130b565b601f1982169083600052806000209160005b8181106113ae57509261090a9492600192827f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169989610611395575b5050811b01905561131f565b85015160001960f88460031b161c191690558980611389565b91928960018192868a01518155019401920161134e565b6113ef908360005287600020601f840160051c810191898510610f5857601f0160051c01906121b9565b866112cd565b634e487b7160e01b600052604160045260246000fd5b61142591925060203d602011610967576109568183611c2c565b9083611288565b826360ec327960e01b60005260045260246000fd5b8263032c20ef60e21b60005260045260246000fd5b346101e75760003660031901126101e75761146f6123d5565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346101e75760003660031901126101e7576020600154604051908152f35b346101e75761151b36611ebe565b9061152581611fe8565b9060a08201516116815760608201805151421061167057602042915101511061165f5760249160206001600160a01b036000541660405194858092630e82f3b760e41b82528660048301525afa9283156105915760009361162b575b50835192602085019384200361161a57608001514201918242116104d2577f50df9e2c9fc5a7f4a07e403fa0300b88fcc8c6943bdff4b8ae71f55b7fd95f899361160c918360005260056020528460066040600020015581519020836000526005602052600c6040600020015560405193849384526020840152606060408401526060830190611d15565b0390a1602060405160018152f35b630d8dbe2560e01b60005260046000fd5b9092506020813d602011611657575b8161164760209383611c2c565b810103126101e757519184611581565b3d915061163a565b633d82a7cd60e11b60005260046000fd5b63a0750b5160e01b60005260046000fd5b633e26347b60e21b60005260045260246000fd5b346101e75760203660031901126101e7576001600160a01b036116b6611ba3565b6116be6123d5565b1680600052600460205260ff6040600020541615611721576020817f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e79260005260048252604060002060ff198154169055604051908152a1602060405160018152f35b6321ac7c5f60e01b60005260045260246000fd5b346101e75760203660031901126101e7577f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc60206004356117746123d5565b8060005260088252611796816001600160a01b0360406000205416151561211c565b806000526008825260406000206001600160a01b03198154169055604051908152a1602060405160018152f35b346101e75760203660031901126101e757610e816117e2600435611fe8565b604051918291602083526020830190611d3a565b346101e75760203660031901126101e757600435600052600560205260206040600020610e8181549160028101546005820154916006810154926007820154936118bd6001600160a01b0360088501541661185360098601611c4e565b906001600160a01b03600a87015416976001600160a01b03600b8801541694600c88015496611889600e600d8b01549a01611c4e565b996040519e8f9e8f908152015260408d015260608c015260808b015260a08a015261018060c08a0152610180890190611d15565b9460e0880152610100870152610120860152610140850152838203610160850152611d15565b346101e75760603660031901126101e7576118fc611ba3565b602435906001600160a01b03821682036101e7577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff821680159081611b01575b6001149081611af7575b159081611aee575b50611add5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556119cc9184611a9e575b506119aa61241d565b6119b261241d565b6119bb336122a4565b6119c660443561223a565b5061234a565b506001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b03821603611a8c575b50611a0f57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b611a989061023d6123d5565b81611a08565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055846119a1565b63f92ee8a960e01b60005260046000fd5b90501585611961565b303b159150611959565b85915061194f565b346101e75760203660031901126101e757600435600052600860205260206001600160a01b0360406000205416604051908152f35b346101e75760203660031901126101e757600435806000526005602052611b78816001600160a01b03600860406000200154161515611f3d565b6000526006602052600260406000206001810154600052016020526020604060002054604051908152f35b600435906001600160a01b03821682036101e757565b90600182811c92168015611be9575b6020831014611bd357565b634e487b7160e01b600052602260045260246000fd5b91607f1691611bc8565b6101c0810190811067ffffffffffffffff8211176113f557604052565b6040810190811067ffffffffffffffff8211176113f557604052565b90601f8019910116810190811067ffffffffffffffff8211176113f557604052565b9060405191826000825492611c6284611bb9565b8084529360018116908115611cd05750600114611c89575b50611c8792500383611c2c565b565b90506000929192526020600020906000915b818310611cb4575050906020611c879282010138611c7a565b6020919350806001915483858901015201910190918492611c9b565b905060209250611c8794915060ff191682840152151560051b82010138611c7a565b60005b838110611d055750506000910152565b8181015183820152602001611cf5565b90602091611d2e81518092818552858086019101611cf2565b601f01601f1916010190565b919091805183526020810151602084016000905b60028210611e3f5750505060408101516060840152606081015192608081016000905b60028210611e29575050611e26929350608082015160c082015260a082015160e082015260c08201516101008201526001600160a01b0360e0830151166101208201526101a0611dd4610100840151610200610140850152610200840190611d15565b926001600160a01b03610120820151166101608401526001600160a01b0361014082015116610180840152610160810151828401526101808101516101c08401520151906101e0818403910152611d15565b90565b6020806001928851815201960191019094611d71565b60208060019263ffffffff865116815201930191019091611d4e565b67ffffffffffffffff81116113f557601f01601f191660200190565b81601f820112156101e757803590611e8e82611e5b565b92611e9c6040519485611c2c565b828452602083830101116101e757816000926020809301838601378301015290565b9060406003198301126101e757600435916024359067ffffffffffffffff82116101e757611e2691600401611e77565b60606003198201126101e7576004359160243567ffffffffffffffff81116101e75782611f1d91600401611e77565b916044359067ffffffffffffffff82116101e757611e2691600401611e77565b15611f455750565b63cd6f4a4f60e01b60005260045260246000fd5b60405190611f6682611bf3565b60606101a0836000815260408051611f7e8282611c2c565b813682376020830152600081830152805190611f9a8183611c2c565b3682378382015260006080820152600060a0820152600060c0820152600060e08201528261010082015260006101208201526000610140820152600061016082015260006101808201520152565b90611ff1611f59565b5081600052600560205260406000209160405161200d81611bf3565b8354815260405163ffffffff6001860154818116835260201c166020820152612037604082611c2c565b6020820152600284015460408201526040518060038601906000905b6002821061210657505050611c8792918161207760406001600160a01b0394611c2c565b606082015260058601546080820152600686015460a0820152600786015460c08201526120f6600e836008890154169760e084019889526120ba60098201611c4e565b61010085015284600a8201541661012085015284600b82015416610140850152600c810154610160850152600d81015461018085015201611c4e565b6101a08201529451161515611f3d565b6001602081928554815201930191019091612053565b156121245750565b6381c4951960e01b60005260045260246000fd5b156121405750565b63166b4d0360e01b60005260045260246000fd5b908160209103126101e7575180151581036101e75790565b611e269392606092825260208201528160408201520190611d15565b156121905750565b604051632f9f8ab960e01b8152602060048201529081906121b5906024830190611d15565b0390fd5b8181106121c4575050565b600081556001016121b9565b60243563ffffffff811681036101e75790565b359063ffffffff821682036101e757565b6024906000905b6002821061220857505050565b60208060019263ffffffff61221c876121e3565b168152019301910190916121fb565b60001981146104d25760010190565b60207fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916122666123d5565b80600155604051908152a1600190565b919060408301926000905b6002821061228e57505050565b6020806001928551815201930191019091612281565b6001600160a01b03168015612334576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b039061235b6123d5565b16801515806123c0575b156123ac576020817f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b6926001600160a01b03196000541617600055604051908152a1600190565b6375ac4eb760e11b60005260045260246000fd5b506001600160a01b0360005416811415612365565b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361240857565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561244c57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081b000a", - "libraries": { - "PoseidonT3": "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93" - }, - "devdoc": { - "errors": { - "InvalidInitialization()": [ - { - "details": "The contract is already initialized." - } - ], - "NotInitializing()": [ - { - "details": "The contract is not initializing." - } - ], - "OwnableInvalidOwner(address)": [ - { - "details": "The owner is not a valid owner account. (eg. `address(0)`)" - } - ], - "OwnableUnauthorizedAccount(address)": [ - { - "details": "The caller account is not authorized to perform an operation." - } - ] - }, - "events": { - "CiphernodeRegistrySet(address)": { - "params": { - "ciphernodeRegistry": "The address of the CiphernodeRegistry contract." - } - }, - "CiphertextOutputPublished(uint256,bytes)": { - "params": { - "ciphertextOutput": "ABI encoded ciphertext output.", - "e3Id": "ID of the E3." - } - }, - "E3Activated(uint256,uint256,bytes)": { - "params": { - "committeePublicKey": "Public key of the committee.", - "e3Id": "ID of the E3.", - "expiration": "Timestamp when committee duties expire." - } - }, - "E3ProgramDisabled(address)": { - "params": { - "e3Program": "The address of the E3 Program." - } - }, - "E3ProgramEnabled(address)": { - "params": { - "e3Program": "The address of the E3 Program." - } - }, - "E3Requested(uint256,(uint256,uint32[2],uint256,uint256[2],uint256,uint256,bytes32,address,bytes,address,address,bytes32,bytes32,bytes),address,address)": { - "params": { - "e3": "Details of the E3.", - "e3Id": "ID of the E3.", - "e3Program": "Address of the Computation module selected.", - "filter": "Address of the pool of nodes from which the Cipher Node committee was selected." - } - }, - "EncryptionSchemeDisabled(bytes32)": { - "params": { - "encryptionSchemeId": "The ID of the encryption scheme that was disabled." - } - }, - "EncryptionSchemeEnabled(bytes32)": { - "params": { - "encryptionSchemeId": "The ID of the encryption scheme that was enabled." - } - }, - "Initialized(uint64)": { - "details": "Triggered when the contract has been initialized or reinitialized." - }, - "InputPublished(uint256,bytes,uint256,uint256)": { - "params": { - "data": "ABI encoded input data.", - "e3Id": "ID of the E3." - } - }, - "MaxDurationSet(uint256)": { - "params": { - "maxDuration": "The maximum duration of a computation in seconds." - } - }, - "PlaintextOutputPublished(uint256,bytes)": { - "params": { - "e3Id": "ID of the E3.", - "plaintextOutput": "ABI encoded plaintext output." - } - } - }, - "kind": "dev", - "methods": { - "activate(uint256,bytes)": { - "details": "This function MUST emit the E3Activated event.This function MUST revert if the given E3 has not yet been requested.This function MUST revert if the selected node committee has not yet published a public key.", - "params": { - "e3Id": "ID of the E3.", - "publicKey": "Public key of the committee." - }, - "returns": { - "success": "True if the E3 was successfully activated." - } - }, - "constructor": { - "params": { - "_maxDuration": "The maximum duration of a computation in seconds", - "_owner": "The owner of this contract" - } - }, - "getE3(uint256)": { - "details": "This function MUST revert if the E3 does not exist.", - "params": { - "e3Id": "ID of the E3." - }, - "returns": { - "e3": "The struct representing the requested E3." - } - }, - "getInputRoot(uint256)": { - "details": "This function MUST revert if the E3 does not exist.", - "params": { - "e3Id": "ID of the E3." - }, - "returns": { - "_0": "The root of the input merkle tree." - } - }, - "initialize(address,address,uint256)": { - "params": { - "_maxDuration": "The maximum duration of a computation in seconds", - "_owner": "The owner of this contract" - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "publishCiphertextOutput(uint256,bytes,bytes)": { - "details": "This function MUST emit the CiphertextOutputPublished event.", - "params": { - "ciphertextOutput": "ABI encoded output data to verify.", - "e3Id": "ID of the E3.", - "proof": "ABI encoded data to verify the ciphertextOutput." - }, - "returns": { - "success": "True if the output was successfully published." - } - }, - "publishInput(uint256,bytes)": { - "details": "This function MUST revert if the E3 is not yet activated.This function MUST emit the InputPublished event.", - "params": { - "data": "ABI encoded input data to publish.", - "e3Id": "ID of the E3." - }, - "returns": { - "success": "True if the input was successfully published." - } - }, - "publishPlaintextOutput(uint256,bytes,bytes)": { - "details": "This function MUST revert if the output has not been published.This function MUST emit the PlaintextOutputPublished event.", - "params": { - "e3Id": "ID of the E3.", - "plaintextOutput": "ABI encoded plaintext output.", - "proof": "ABI encoded data to verify the plaintextOutput." - } - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." - }, - "request(address,uint32[2],uint256[2],uint256,address,bytes,bytes)": { - "details": "This function MUST emit the E3Requested event.", - "params": { - "computeProviderParams": "ABI encoded compute provider parameters.", - "duration": "The duration of the computation in seconds.", - "e3Program": "Address of the E3 Program.", - "e3ProgramParams": "ABI encoded computation parameters.", - "filter": "IDs of the pool of nodes from which to select the committee.", - "threshold": "The M/N threshold for the committee." - }, - "returns": { - "e3": "The E3 struct.", - "e3Id": "ID of the E3." - } - }, - "setMaxDuration(uint256)": { - "params": { - "_maxDuration": "The maximum duration of a computation in seconds." - }, - "returns": { - "success": "True if the max duration was successfully set." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "version": 1 - }, - "userdoc": { - "events": { - "CiphernodeRegistrySet(address)": { - "notice": "This event MUST be emitted any time the CiphernodeRegistry is set." - }, - "CiphertextOutputPublished(uint256,bytes)": { - "notice": "This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published." - }, - "E3Activated(uint256,uint256,bytes)": { - "notice": "This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated." - }, - "E3ProgramDisabled(address)": { - "notice": "This event MUST be emitted any time a E3 Program is disabled." - }, - "E3ProgramEnabled(address)": { - "notice": "This event MUST be emitted any time a E3 Program is enabled." - }, - "E3Requested(uint256,(uint256,uint32[2],uint256,uint256[2],uint256,uint256,bytes32,address,bytes,address,address,bytes32,bytes32,bytes),address,address)": { - "notice": "This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested." - }, - "EncryptionSchemeDisabled(bytes32)": { - "notice": "This event MUST be emitted any time an encryption scheme is disabled." - }, - "EncryptionSchemeEnabled(bytes32)": { - "notice": "The event MUST be emitted any time an encryption scheme is enabled." - }, - "InputPublished(uint256,bytes,uint256,uint256)": { - "notice": "This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published." - }, - "MaxDurationSet(uint256)": { - "notice": "This event MUST be emitted any time the `maxDuration` is set." - }, - "PlaintextOutputPublished(uint256,bytes)": { - "notice": "This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published." - } - }, - "kind": "user", - "methods": { - "activate(uint256,bytes)": { - "notice": "This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input." - }, - "getE3(uint256)": { - "notice": "This function should be called to retrieve the details of an Encrypted Execution Environment (E3)." - }, - "getInputRoot(uint256)": { - "notice": "This function returns root of the input merkle tree for a given E3." - }, - "publishCiphertextOutput(uint256,bytes,bytes)": { - "notice": "This function should be called to publish output data for an Encrypted Execution Environment (E3)." - }, - "publishInput(uint256,bytes)": { - "notice": "This function should be called to publish input data for Encrypted Execution Environment (E3)." - }, - "publishPlaintextOutput(uint256,bytes,bytes)": { - "notice": "This function publishes the plaintext output of an Encrypted Execution Environment (E3)." - }, - "request(address,uint32[2],uint256[2],uint256,address,bytes,bytes)": { - "notice": "This function should be called to request a computation within an Encrypted Execution Environment (E3)." - }, - "setMaxDuration(uint256)": { - "notice": "This function should be called to set the maximum duration of requested computations." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1382, - "contract": "contracts/Enclave.sol:Enclave", - "label": "ciphernodeRegistry", - "offset": 0, - "slot": "0", - "type": "t_contract(ICiphernodeRegistry)2537" - }, - { - "astId": 1384, - "contract": "contracts/Enclave.sol:Enclave", - "label": "maxDuration", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 1386, - "contract": "contracts/Enclave.sol:Enclave", - "label": "nexte3Id", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 1388, - "contract": "contracts/Enclave.sol:Enclave", - "label": "requests", - "offset": 0, - "slot": "3", - "type": "t_uint256" - }, - { - "astId": 1393, - "contract": "contracts/Enclave.sol:Enclave", - "label": "e3Programs", - "offset": 0, - "slot": "4", - "type": "t_mapping(t_contract(IE3Program)2631,t_bool)" - }, - { - "astId": 1398, - "contract": "contracts/Enclave.sol:Enclave", - "label": "e3s", - "offset": 0, - "slot": "5", - "type": "t_mapping(t_uint256,t_struct(E3)2597_storage)" - }, - { - "astId": 1403, - "contract": "contracts/Enclave.sol:Enclave", - "label": "inputs", - "offset": 0, - "slot": "6", - "type": "t_mapping(t_uint256,t_struct(LeanIMTData)518_storage)" - }, - { - "astId": 1407, - "contract": "contracts/Enclave.sol:Enclave", - "label": "inputCounts", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 1412, - "contract": "contracts/Enclave.sol:Enclave", - "label": "decryptionVerifiers", - "offset": 0, - "slot": "8", - "type": "t_mapping(t_bytes32,t_contract(IDecryptionVerifier)2552)" - } - ], - "types": { - "t_array(t_uint256)2_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[2]", - "numberOfBytes": "64" - }, - "t_array(t_uint32)2_storage": { - "base": "t_uint32", - "encoding": "inplace", - "label": "uint32[2]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(ICiphernodeRegistry)2537": { - "encoding": "inplace", - "label": "contract ICiphernodeRegistry", - "numberOfBytes": "20" - }, - "t_contract(IDecryptionVerifier)2552": { - "encoding": "inplace", - "label": "contract IDecryptionVerifier", - "numberOfBytes": "20" - }, - "t_contract(IE3Program)2631": { - "encoding": "inplace", - "label": "contract IE3Program", - "numberOfBytes": "20" - }, - "t_contract(IInputValidator)2826": { - "encoding": "inplace", - "label": "contract IInputValidator", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_contract(IDecryptionVerifier)2552)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => contract IDecryptionVerifier)", - "numberOfBytes": "32", - "value": "t_contract(IDecryptionVerifier)2552" - }, - "t_mapping(t_contract(IE3Program)2631,t_bool)": { - "encoding": "mapping", - "key": "t_contract(IE3Program)2631", - "label": "mapping(contract IE3Program => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_uint256,t_struct(E3)2597_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct E3)", - "numberOfBytes": "32", - "value": "t_struct(E3)2597_storage" - }, - "t_mapping(t_uint256,t_struct(LeanIMTData)518_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct LeanIMTData)", - "numberOfBytes": "32", - "value": "t_struct(LeanIMTData)518_storage" - }, - "t_mapping(t_uint256,t_uint256)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_struct(E3)2597_storage": { - "encoding": "inplace", - "label": "struct E3", - "members": [ - { - "astId": 2563, - "contract": "contracts/Enclave.sol:Enclave", - "label": "seed", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 2567, - "contract": "contracts/Enclave.sol:Enclave", - "label": "threshold", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint32)2_storage" - }, - { - "astId": 2569, - "contract": "contracts/Enclave.sol:Enclave", - "label": "requestBlock", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 2573, - "contract": "contracts/Enclave.sol:Enclave", - "label": "startWindow", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)2_storage" - }, - { - "astId": 2575, - "contract": "contracts/Enclave.sol:Enclave", - "label": "duration", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 2577, - "contract": "contracts/Enclave.sol:Enclave", - "label": "expiration", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 2579, - "contract": "contracts/Enclave.sol:Enclave", - "label": "encryptionSchemeId", - "offset": 0, - "slot": "7", - "type": "t_bytes32" - }, - { - "astId": 2582, - "contract": "contracts/Enclave.sol:Enclave", - "label": "e3Program", - "offset": 0, - "slot": "8", - "type": "t_contract(IE3Program)2631" - }, - { - "astId": 2584, - "contract": "contracts/Enclave.sol:Enclave", - "label": "e3ProgramParams", - "offset": 0, - "slot": "9", - "type": "t_bytes_storage" - }, - { - "astId": 2587, - "contract": "contracts/Enclave.sol:Enclave", - "label": "inputValidator", - "offset": 0, - "slot": "10", - "type": "t_contract(IInputValidator)2826" - }, - { - "astId": 2590, - "contract": "contracts/Enclave.sol:Enclave", - "label": "decryptionVerifier", - "offset": 0, - "slot": "11", - "type": "t_contract(IDecryptionVerifier)2552" - }, - { - "astId": 2592, - "contract": "contracts/Enclave.sol:Enclave", - "label": "committeePublicKey", - "offset": 0, - "slot": "12", - "type": "t_bytes32" - }, - { - "astId": 2594, - "contract": "contracts/Enclave.sol:Enclave", - "label": "ciphertextOutput", - "offset": 0, - "slot": "13", - "type": "t_bytes32" - }, - { - "astId": 2596, - "contract": "contracts/Enclave.sol:Enclave", - "label": "plaintextOutput", - "offset": 0, - "slot": "14", - "type": "t_bytes_storage" - } - ], - "numberOfBytes": "480" - }, - "t_struct(LeanIMTData)518_storage": { - "encoding": "inplace", - "label": "struct LeanIMTData", - "members": [ - { - "astId": 507, - "contract": "contracts/Enclave.sol:Enclave", - "label": "size", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 509, - "contract": "contracts/Enclave.sol:Enclave", - "label": "depth", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 513, - "contract": "contracts/Enclave.sol:Enclave", - "label": "sideNodes", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 517, - "contract": "contracts/Enclave.sol:Enclave", - "label": "leaves", - "offset": 0, - "slot": "3", - "type": "t_mapping(t_uint256,t_uint256)" - } - ], - "numberOfBytes": "128" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint32": { - "encoding": "inplace", - "label": "uint32", - "numberOfBytes": "4" - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/MockComputeProvider.json b/packages/enclave-contracts/deployments/sepolia/MockComputeProvider.json deleted file mode 100644 index 8f8277f318..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/MockComputeProvider.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "address": "0xbB2735f8190c023c1523858a2dcdF9726C895F18", - "abi": [ - { - "inputs": [], - "name": "invalidParams", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "params", - "type": "bytes" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "contract IDecryptionVerifier", - "name": "decryptionVerifier", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0xb9f2d9641189b761c66fc496da0bbcf9914d6a40ffbd37ea613c71b3f2e50a1d", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0xbB2735f8190c023c1523858a2dcdF9726C895F18", - "transactionIndex": 27, - "gasUsed": "128651", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x376831e31160384cdafcc7e8522c8a72d8f8ad4b3a11509c8deaba957e04264c", - "transactionHash": "0xb9f2d9641189b761c66fc496da0bbcf9914d6a40ffbd37ea613c71b3f2e50a1d", - "logs": [], - "blockNumber": 6982717, - "cumulativeGasUsed": "6411800", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "c9b7037486bd8b1125ffad462d6531cb", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"invalidParams\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"name\":\"validate\",\"outputs\":[{\"internalType\":\"contract IDecryptionVerifier\",\"name\":\"decryptionVerifier\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/MockComputeProvider.sol\":\"MockComputeProvider\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/interfaces/IComputeProvider.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IDecryptionVerifier } from \\\"./IDecryptionVerifier.sol\\\";\\n\\ninterface IComputeProvider {\\n /// @notice This function should be called by the Enclave contract to validate the compute provider parameters.\\n /// @param params ABI encoded compute provider parameters.\\n function validate(\\n uint256 e3Id,\\n uint256 seed,\\n bytes calldata params\\n ) external returns (IDecryptionVerifier decryptionVerifier);\\n}\\n\",\"keccak256\":\"0x265fea4a55770649aca73fbf4d7ccc01ba654565ec18247597b73d36dac27fe1\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IDecryptionVerifier.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IDecryptionVerifier {\\n /// @notice This function should be called by the Enclave contract to verify the\\n /// decryption of output of a computation.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\\n /// @param proof ABI encoded proof of the given output hash.\\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\\n function verify(\\n uint256 e3Id,\\n bytes32 plaintextOutputHash,\\n bytes memory proof\\n ) external view returns (bool success);\\n}\\n\",\"keccak256\":\"0xb92991a581d3c18cdc273497687ec1c6e3016674314f21fe56917aece5d10863\",\"license\":\"LGPL-3.0-only\"},\"contracts/test/MockComputeProvider.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport {\\n IComputeProvider,\\n IDecryptionVerifier\\n} from \\\"../interfaces/IComputeProvider.sol\\\";\\n\\ncontract MockComputeProvider is IComputeProvider {\\n error invalidParams();\\n\\n function validate(\\n uint256,\\n uint256,\\n bytes memory params\\n ) external pure returns (IDecryptionVerifier decryptionVerifier) {\\n require(params.length == 32, invalidParams());\\n // solhint-disable no-inline-assembly\\n assembly {\\n decryptionVerifier := mload(add(params, 32))\\n }\\n (decryptionVerifier) = abi.decode(params, (IDecryptionVerifier));\\n }\\n}\\n\",\"keccak256\":\"0x129807f1fc79c9cdd1fff120a39f91f8d31826ac9a6fe4e2d714c5ee1bd367aa\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", - "bytecode": "0x6080806040523460155761015d908161001b8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c6323e7fd591461002757600080fd5b346100ea5760603660031901126100ea5760443567ffffffffffffffff81116100ea57366023820112156100ea5780600401359067ffffffffffffffff82116100ef57604051601f8301601f19908116603f0116810167ffffffffffffffff8111828210176100ef5760405282815236602484840101116100ea5760006020846100e69560246100bf96018386013783010152610105565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b602081510361013f576020818051810103126100ea576020015173ffffffffffffffffffffffffffffffffffffffff811681036100ea5790565b63be64db2760e01b60005260046000fdfea164736f6c634300081b000a", - "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c6323e7fd591461002757600080fd5b346100ea5760603660031901126100ea5760443567ffffffffffffffff81116100ea57366023820112156100ea5780600401359067ffffffffffffffff82116100ef57604051601f8301601f19908116603f0116810167ffffffffffffffff8111828210176100ef5760405282815236602484840101116100ea5760006020846100e69560246100bf96018386013783010152610105565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b602081510361013f576020818051810103126100ea576020015173ffffffffffffffffffffffffffffffffffffffff811681036100ea5790565b63be64db2760e01b60005260046000fdfea164736f6c634300081b000a", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/MockDecryptionVerifier.json b/packages/enclave-contracts/deployments/sepolia/MockDecryptionVerifier.json deleted file mode 100644 index d787cfbcd2..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/MockDecryptionVerifier.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "address": "0x1C768fB51e9D33EE1eE9E725cE9241f73a0A2047", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0x5c5d61983080c09c801c48fa04b050b7310abe2dab1b69e313f8820ac57f34dd", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0x1C768fB51e9D33EE1eE9E725cE9241f73a0A2047", - "transactionIndex": 9, - "gasUsed": "103723", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4197779e4354ae92153585d34224d8f73f7f1473cab9fad2c39b82ac3bb73559", - "transactionHash": "0x5c5d61983080c09c801c48fa04b050b7310abe2dab1b69e313f8820ac57f34dd", - "logs": [], - "blockNumber": 6982718, - "cumulativeGasUsed": "609655", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "c9b7037486bd8b1125ffad462d6531cb", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/MockDecryptionVerifier.sol\":\"MockDecryptionVerifier\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/interfaces/IDecryptionVerifier.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IDecryptionVerifier {\\n /// @notice This function should be called by the Enclave contract to verify the\\n /// decryption of output of a computation.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\\n /// @param proof ABI encoded proof of the given output hash.\\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\\n function verify(\\n uint256 e3Id,\\n bytes32 plaintextOutputHash,\\n bytes memory proof\\n ) external view returns (bool success);\\n}\\n\",\"keccak256\":\"0xb92991a581d3c18cdc273497687ec1c6e3016674314f21fe56917aece5d10863\",\"license\":\"LGPL-3.0-only\"},\"contracts/test/MockDecryptionVerifier.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IDecryptionVerifier } from \\\"../interfaces/IDecryptionVerifier.sol\\\";\\n\\ncontract MockDecryptionVerifier is IDecryptionVerifier {\\n function verify(\\n uint256,\\n bytes32,\\n bytes memory data\\n ) external pure returns (bool success) {\\n data;\\n\\n if (data.length > 0) success = true;\\n }\\n}\\n\",\"keccak256\":\"0x85a320eb4c9079cf73b32a259cd8709ad0c4475171521ab92adb2e9a863faf8d\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", - "bytecode": "0x6080806040523460145760e9908161001a8239f35b600080fdfe60806004361015600e57600080fd5b60003560e01c632f0e1bbf14602257600080fd5b3460c157606036600319011260c15760443567ffffffffffffffff811160c1573660238201121560c15780600401359067ffffffffffffffff821160c657601f8201601f19908116603f0116830167ffffffffffffffff81118482101760c657604052818352366024838301011160c1578160009260246020930183860137830101526000905160ba575b6020906040519015158152f35b50600160ad565b600080fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c634300081b000a", - "deployedBytecode": "0x60806004361015600e57600080fd5b60003560e01c632f0e1bbf14602257600080fd5b3460c157606036600319011260c15760443567ffffffffffffffff811160c1573660238201121560c15780600401359067ffffffffffffffff821160c657601f8201601f19908116603f0116830167ffffffffffffffff81118482101760c657604052818352366024838301011160c1578160009260246020930183860137830101526000905160ba575b6020906040519015158152f35b50600160ad565b600080fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c634300081b000a", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/MockE3Program.json b/packages/enclave-contracts/deployments/sepolia/MockE3Program.json deleted file mode 100644 index 4ea5a400d6..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/MockE3Program.json +++ /dev/null @@ -1,233 +0,0 @@ -{ - "address": "0xc7fe6Ee2e3e3Da8E1448B3531f92c676B06257b5", - "abi": [ - { - "inputs": [ - { - "internalType": "contract IInputValidator", - "name": "_inputValidator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "E3AlreadyInitialized", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInputValidator", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "computeProviderParams", - "type": "bytes" - } - ], - "name": "invalidParams", - "type": "error" - }, - { - "inputs": [], - "name": "ENCRYPTION_SCHEME_ID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "inputValidator", - "outputs": [ - { - "internalType": "contract IInputValidator", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "paramsHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "paramsHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "e3ProgramParams", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "computeProviderParams", - "type": "bytes" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "contract IInputValidator", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0x3876bae2247b8651c1c466eab1db3a97142acfe6206f3b7e5e5b9433b9211f91", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0xc7fe6Ee2e3e3Da8E1448B3531f92c676B06257b5", - "transactionIndex": 128, - "gasUsed": "266938", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc34a49bf1984733b779b846db46955d9c8232e6fad570601530fd81b5da4aea7", - "transactionHash": "0x3876bae2247b8651c1c466eab1db3a97142acfe6206f3b7e5e5b9433b9211f91", - "logs": [], - "blockNumber": 8332813, - "cumulativeGasUsed": "12236361", - "status": 1, - "byzantium": true - }, - "args": [ - "0xe2be22b924CAF680500497f5Ba77A927EbdeD1Ae" - ], - "numDeployments": 2, - "solcInputHash": "f32a0aa4ee06fa210859a817cc9dafc5", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IInputValidator\",\"name\":\"_inputValidator\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"E3AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInputValidator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"computeProviderParams\",\"type\":\"bytes\"}],\"name\":\"invalidParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ENCRYPTION_SCHEME_ID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inputValidator\",\"outputs\":[{\"internalType\":\"contract IInputValidator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"paramsHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"paramsHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"e3ProgramParams\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"computeProviderParams\",\"type\":\"bytes\"}],\"name\":\"validate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/MockE3Program.sol\":\"MockE3Program\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/interfaces/IE3Program.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IInputValidator } from \\\"./IInputValidator.sol\\\";\\n\\ninterface IE3Program {\\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\\n /// @param e3Id ID of the E3.\\n /// @param seed Seed for the computation.\\n /// @param e3ProgramParams ABI encoded computation parameters.\\n /// @param computeProviderParams ABI encoded compute provider parameters.\\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\\n /// @return inputValidator The input validator to be used for the computation.\\n function validate(\\n uint256 e3Id,\\n uint256 seed,\\n bytes calldata e3ProgramParams,\\n bytes calldata computeProviderParams\\n )\\n external\\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\\n\\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\\n /// @param e3Id ID of the E3.\\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\\n /// @return success Whether the output data is valid.\\n function verify(\\n uint256 e3Id,\\n bytes32 ciphertextOutputHash,\\n bytes memory proof\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0xd60e92b5b6498daf0b7f1238d354156c67d25c03caaaabbc601368e9e4a295b2\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IInputValidator.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IInputValidator {\\n /// @notice This function should be called by the Enclave contract to validate the\\n /// input of a computation.\\n /// @param sender The account that is submitting the input.\\n /// @param data The input to be verified.\\n /// @return input The decoded, policy-approved application payload.\\n function validate(\\n address sender,\\n bytes memory data\\n ) external returns (bytes memory input);\\n}\\n\",\"keccak256\":\"0x20d4016bd59c317c5571cfe6c3e8f46cbabddc0b926dc64019eeae8d29788653\",\"license\":\"LGPL-3.0-only\"},\"contracts/test/MockE3Program.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IE3Program, IInputValidator } from \\\"../interfaces/IE3Program.sol\\\";\\n\\ncontract MockE3Program is IE3Program {\\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\\n error InvalidInputValidator();\\n error E3AlreadyInitialized();\\n bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256(\\\"fhe.rs:BFV\\\");\\n\\n IInputValidator public inputValidator;\\n mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes;\\n\\n constructor(IInputValidator _inputValidator) {\\n if (address(_inputValidator) == address(0)) {\\n revert InvalidInputValidator();\\n }\\n\\n inputValidator = _inputValidator;\\n }\\n\\n function validate(\\n uint256 e3Id,\\n uint256,\\n bytes calldata e3ProgramParams,\\n bytes calldata computeProviderParams\\n ) external returns (bytes32, IInputValidator) {\\n require(\\n computeProviderParams.length == 32,\\n invalidParams(e3ProgramParams, computeProviderParams)\\n );\\n\\n require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized());\\n paramsHashes[e3Id] = keccak256(e3ProgramParams);\\n\\n paramsHashes[e3Id] = keccak256(e3ProgramParams);\\n return (ENCRYPTION_SCHEME_ID, inputValidator);\\n }\\n\\n function verify(\\n uint256,\\n bytes32,\\n bytes memory data\\n ) external pure returns (bool success) {\\n data;\\n if (data.length > 0) success = true;\\n }\\n}\\n\",\"keccak256\":\"0x0234622000a090d14b9f5c1690e6b24af5f14f7537b75fe40a71ae277d47faec\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", - "bytecode": "0x608034608657601f61040c38819003918201601f19168301916001600160401b03831184841017608b57808492602094604052833981010312608657516001600160a01b038116908190036086578015607557600080546001600160a01b03191691909117905560405161036a90816100a28239f35b6310160a0760e11b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c908163143c083614610277575080632f0e1bbf1461021757806378d89187146101dc578063a3926079146101a85763a61d7e3e1461005657600080fd5b346101a35760803660031901126101a35760043560443567ffffffffffffffff81116101a35761008a90369060040161030e565b9060643567ffffffffffffffff81116101a3576100ab90369060040161030e565b60208103610163575050826000526001602052604060002054610152576100f4916100d736828461029f565b60208151910120846000526001602052604060002055369161029f565b60208151910120906000526001602052604060002055604073ffffffffffffffffffffffffffffffffffffffff600054168151907f2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c682526020820152f35b6335751e3760e11b60005260046000fd5b61019f92945061018d6040519586956312bed5ff60e31b875260406004880152604487019161033c565b8481036003190160248601529161033c565b0390fd5b600080fd5b346101a35760003660031901126101a357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101a35760003660031901126101a35760206040517f2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c68152f35b346101a35760603660031901126101a35760443567ffffffffffffffff81116101a357366023820112156101a35761025990369060248160040135910161029f565b6000905161026f575b6020906040519015158152f35b506001610262565b346101a35760203660031901126101a357602090600435600052600182526040600020548152f35b92919267ffffffffffffffff82116102f85760405191601f8101601f19908116603f0116830167ffffffffffffffff8111848210176102f8576040528294818452818301116101a3578281602093846000960137010152565b634e487b7160e01b600052604160045260246000fd5b9181601f840112156101a35782359167ffffffffffffffff83116101a357602083818601950101116101a357565b908060209392818452848401376000828201840152601f01601f191601019056fea164736f6c634300081b000a", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b60003560e01c908163143c083614610277575080632f0e1bbf1461021757806378d89187146101dc578063a3926079146101a85763a61d7e3e1461005657600080fd5b346101a35760803660031901126101a35760043560443567ffffffffffffffff81116101a35761008a90369060040161030e565b9060643567ffffffffffffffff81116101a3576100ab90369060040161030e565b60208103610163575050826000526001602052604060002054610152576100f4916100d736828461029f565b60208151910120846000526001602052604060002055369161029f565b60208151910120906000526001602052604060002055604073ffffffffffffffffffffffffffffffffffffffff600054168151907f2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c682526020820152f35b6335751e3760e11b60005260046000fd5b61019f92945061018d6040519586956312bed5ff60e31b875260406004880152604487019161033c565b8481036003190160248601529161033c565b0390fd5b600080fd5b346101a35760003660031901126101a357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101a35760003660031901126101a35760206040517f2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c68152f35b346101a35760603660031901126101a35760443567ffffffffffffffff81116101a357366023820112156101a35761025990369060248160040135910161029f565b6000905161026f575b6020906040519015158152f35b506001610262565b346101a35760203660031901126101a357602090600435600052600182526040600020548152f35b92919267ffffffffffffffff82116102f85760405191601f8101601f19908116603f0116830167ffffffffffffffff8111848210176102f8576040528294818452818301116101a3578281602093846000960137010152565b634e487b7160e01b600052604160045260246000fd5b9181601f840112156101a35782359167ffffffffffffffff83116101a357602083818601950101116101a357565b908060209392818452848401376000828201840152601f01601f191601019056fea164736f6c634300081b000a", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 71, - "contract": "contracts/test/MockE3Program.sol:MockE3Program", - "label": "inputValidator", - "offset": 0, - "slot": "0", - "type": "t_contract(IInputValidator)46" - }, - { - "astId": 75, - "contract": "contracts/test/MockE3Program.sol:MockE3Program", - "label": "paramsHashes", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_uint256,t_bytes32)" - } - ], - "types": { - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IInputValidator)46": { - "encoding": "inplace", - "label": "contract IInputValidator", - "numberOfBytes": "20" - }, - "t_mapping(t_uint256,t_bytes32)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bytes32)", - "numberOfBytes": "32", - "value": "t_bytes32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/MockInputValidator.json b/packages/enclave-contracts/deployments/sepolia/MockInputValidator.json deleted file mode 100644 index 1406a83209..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/MockInputValidator.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "address": "0xe2be22b924CAF680500497f5Ba77A927EbdeD1Ae", - "abi": [ - { - "inputs": [], - "name": "InvalidInput", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bytes", - "name": "input", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0xe3bc8ded11d3d01c8274925fb6098ead7d18e415696d76147e7ae07cff5e240c", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0xe2be22b924CAF680500497f5Ba77A927EbdeD1Ae", - "transactionIndex": 158, - "gasUsed": "133279", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2c7450e1b75de04dc93b47579d785d6f1cbdeefaec14dff79b643a434b7c9d37", - "transactionHash": "0xe3bc8ded11d3d01c8274925fb6098ead7d18e415696d76147e7ae07cff5e240c", - "logs": [], - "blockNumber": 8332812, - "cumulativeGasUsed": "15860788", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "f32a0aa4ee06fa210859a817cc9dafc5", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"validate\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"validate(address,bytes)\":{\"params\":{\"data\":\"The input to be verified.\",\"sender\":\"The account that is submitting the input.\"},\"returns\":{\"input\":\"The decoded, policy-approved application payload.\"}}},\"title\":\"MockInputValidator.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"validate(address,bytes)\":{\"notice\":\"Validates input\"}},\"notice\":\"Enclave Input Validator\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/MockInputValidator.sol\":\"MockInputValidator\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/interfaces/IInputValidator.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IInputValidator {\\n /// @notice This function should be called by the Enclave contract to validate the\\n /// input of a computation.\\n /// @param sender The account that is submitting the input.\\n /// @param data The input to be verified.\\n /// @return input The decoded, policy-approved application payload.\\n function validate(\\n address sender,\\n bytes memory data\\n ) external returns (bytes memory input);\\n}\\n\",\"keccak256\":\"0x20d4016bd59c317c5571cfe6c3e8f46cbabddc0b926dc64019eeae8d29788653\",\"license\":\"LGPL-3.0-only\"},\"contracts/test/MockInputValidator.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { IInputValidator } from \\\"../interfaces/IInputValidator.sol\\\";\\n\\n/// @title MockInputValidator.\\n/// @notice Enclave Input Validator\\ncontract MockInputValidator is IInputValidator {\\n error InvalidInput();\\n\\n /// @notice Validates input\\n /// @param sender The account that is submitting the input.\\n /// @param data The input to be verified.\\n /// @return input The decoded, policy-approved application payload.\\n function validate(\\n address sender,\\n bytes memory data\\n ) external pure returns (bytes memory input) {\\n if (data.length == 3 || sender == address(0)) {\\n revert InvalidInput();\\n }\\n\\n input = data;\\n }\\n}\\n\",\"keccak256\":\"0x59f5459aa10a90d47c6971e4bc66781539cb71734fa6817f447a8118603cd4cf\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", - "bytecode": "0x60808060405234601557610172908161001b8239f35b600080fdfe6080600436101561000f57600080fd5b60003560e01c63caf927851461002457600080fd5b3461014a57604036600319011261014a5760043573ffffffffffffffffffffffffffffffffffffffff811680910361014a5760243567ffffffffffffffff811161014a573660238201121561014a5780600401359067ffffffffffffffff821161014f57601f8201601f19908116603f0116840167ffffffffffffffff81118582101761014f57604052818452366024838301011161014a578160009260246020930183870137840101526003825114908115610141575b506101305760405190602082528181519182602083015260005b8381106101185750508160006040809484010152601f80199101168101030190f35b602082820181015160408784010152859350016100f6565b63b4fa3fb360e01b60005260046000fd5b905015386100dc565b600080fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c634300081b000a", - "deployedBytecode": "0x6080600436101561000f57600080fd5b60003560e01c63caf927851461002457600080fd5b3461014a57604036600319011261014a5760043573ffffffffffffffffffffffffffffffffffffffff811680910361014a5760243567ffffffffffffffff811161014a573660238201121561014a5780600401359067ffffffffffffffff821161014f57601f8201601f19908116603f0116840167ffffffffffffffff81118582101761014f57604052818452366024838301011161014a578160009260246020930183870137840101526003825114908115610141575b506101305760405190602082528181519182602083015260005b8381106101185750508160006040809484010152601f80199101168101030190f35b602082820181015160408784010152859350016100f6565b63b4fa3fb360e01b60005260046000fd5b905015386100dc565b600080fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c634300081b000a", - "devdoc": { - "kind": "dev", - "methods": { - "validate(address,bytes)": { - "params": { - "data": "The input to be verified.", - "sender": "The account that is submitting the input." - }, - "returns": { - "input": "The decoded, policy-approved application payload." - } - } - }, - "title": "MockInputValidator.", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "validate(address,bytes)": { - "notice": "Validates input" - } - }, - "notice": "Enclave Input Validator", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/NaiveRegistryFilter.json b/packages/enclave-contracts/deployments/sepolia/NaiveRegistryFilter.json deleted file mode 100644 index e38068c632..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/NaiveRegistryFilter.json +++ /dev/null @@ -1,491 +0,0 @@ -{ - "address": "0x22f12b41DBb19fe7C7c72566BA403798D946FEF3", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_registry", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "ciphernode", - "type": "address" - } - ], - "name": "CiphernodeNotEnabled", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeAlreadyPublished", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeDoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "CommitteeNotPublished", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRegistry", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3", - "type": "uint256" - } - ], - "name": "committees", - "outputs": [ - { - "internalType": "bytes32", - "name": "publicKey", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "getCommittee", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "nodes", - "type": "address[]" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - }, - { - "internalType": "bytes32", - "name": "publicKey", - "type": "bytes32" - } - ], - "internalType": "struct NaiveRegistryFilter.Committee", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_registry", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "nodes", - "type": "address[]" - }, - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - } - ], - "name": "publishCommittee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "uint32[2]", - "name": "threshold", - "type": "uint32[2]" - } - ], - "name": "requestCommittee", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_registry", - "type": "address" - } - ], - "name": "setRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xa5f1477ed13ce30b7501513de14a1fc2d16477f6dff4fe274838426b7fa3cee3", - "receipt": { - "to": null, - "from": "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "contractAddress": "0x22f12b41DBb19fe7C7c72566BA403798D946FEF3", - "transactionIndex": 148, - "gasUsed": "771935", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000001000000001000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000002800000000000000000000004080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000000000020", - "blockHash": "0x991d9ea05f561d1256896b16f918f2b3c564603a0b6dee93ff9abf06d3bb3be0", - "transactionHash": "0xa5f1477ed13ce30b7501513de14a1fc2d16477f6dff4fe274838426b7fa3cee3", - "logs": [ - { - "transactionIndex": 148, - "blockNumber": 8360700, - "transactionHash": "0xa5f1477ed13ce30b7501513de14a1fc2d16477f6dff4fe274838426b7fa3cee3", - "address": "0x22f12b41DBb19fe7C7c72566BA403798D946FEF3", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000008837e47c4bb520ade83aab761c3b60679443af1b" - ], - "data": "0x", - "logIndex": 231, - "blockHash": "0x991d9ea05f561d1256896b16f918f2b3c564603a0b6dee93ff9abf06d3bb3be0" - }, - { - "transactionIndex": 148, - "blockNumber": 8360700, - "transactionHash": "0xa5f1477ed13ce30b7501513de14a1fc2d16477f6dff4fe274838426b7fa3cee3", - "address": "0x22f12b41DBb19fe7C7c72566BA403798D946FEF3", - "topics": [ - "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 232, - "blockHash": "0x991d9ea05f561d1256896b16f918f2b3c564603a0b6dee93ff9abf06d3bb3be0" - } - ], - "blockNumber": 8360700, - "cumulativeGasUsed": "15583856", - "status": 1, - "byzantium": true - }, - "args": [ - "0x8837e47c4Bb520ADE83AAB761C3B60679443af1B", - "0x4A6701c770c53584b7d781ccC0267152d128bd4E" - ], - "numDeployments": 3, - "solcInputHash": "7505270e9ddb813a3809c10e5d95f372", - "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_registry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"ciphernode\",\"type\":\"address\"}],\"name\":\"CiphernodeNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeNotPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3\",\"type\":\"uint256\"}],\"name\":\"committees\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"publicKey\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"getCommittee\",\"outputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"nodes\",\"type\":\"address[]\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"bytes32\",\"name\":\"publicKey\",\"type\":\"bytes32\"}],\"internalType\":\"struct NaiveRegistryFilter.Committee\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_registry\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"nodes\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"publishCommittee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"requestCommittee\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_registry\",\"type\":\"address\"}],\"name\":\"setRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/registry/NaiveRegistryFilter.sol\":\"NaiveRegistryFilter\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"contracts/interfaces/ICiphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface ICiphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeAdded(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\\n /// @param node Address of the ciphernode.\\n /// @param index Index of the ciphernode in the registry.\\n /// @param numNodes Number of ciphernodes in the registry.\\n /// @param size Size of the registry.\\n event CiphernodeRemoved(\\n address indexed node,\\n uint256 index,\\n uint256 numNodes,\\n uint256 size\\n );\\n\\n function isCiphernodeEligible(address ciphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The hash of the public key generated by the given committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKeyHash The hash of the public key of the given committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes32 publicKeyHash);\\n}\\n\",\"keccak256\":\"0xe24e6322e8c6fc83461edfbdbedb409e243f1c4e79021a74585cfe875c225aa2\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\ninterface IRegistryFilter {\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0x6bd13d0b188e54393b1a030a43f95042161091d49428e880c301d882c4583100\",\"license\":\"LGPL-3.0-only\"},\"contracts/registry/NaiveRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.27;\\n\\nimport { ICiphernodeRegistry } from \\\"../interfaces/ICiphernodeRegistry.sol\\\";\\nimport { IRegistryFilter } from \\\"../interfaces/IRegistryFilter.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\\n struct Committee {\\n address[] nodes;\\n uint32[2] threshold;\\n bytes32 publicKey;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n address public registry;\\n\\n mapping(uint256 e3 => Committee committee) public committees;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeAlreadyExists();\\n error CommitteeAlreadyPublished();\\n error CommitteeDoesNotExist();\\n error CommitteeNotPublished();\\n error CiphernodeNotEnabled(address ciphernode);\\n error OnlyRegistry();\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Modifiers //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n modifier onlyRegistry() {\\n require(msg.sender == registry, OnlyRegistry());\\n _;\\n }\\n\\n modifier onlyOwnerOrCiphernode() {\\n require(\\n msg.sender == owner() ||\\n ICiphernodeRegistry(registry).isCiphernodeEligible(msg.sender),\\n CiphernodeNotEnabled(msg.sender)\\n );\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n constructor(address _owner, address _registry) {\\n initialize(_owner, _registry);\\n }\\n\\n function initialize(address _owner, address _registry) public initializer {\\n __Ownable_init(msg.sender);\\n setRegistry(_registry);\\n if (_owner != owner()) transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external onlyRegistry returns (bool success) {\\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\\n committees[e3Id].threshold = threshold;\\n success = true;\\n }\\n\\n function publishCommittee(\\n uint256 e3Id,\\n address[] memory nodes,\\n bytes memory publicKey\\n ) external onlyOwner {\\n Committee storage committee = committees[e3Id];\\n require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished());\\n committee.nodes = nodes;\\n committee.publicKey = keccak256(publicKey);\\n ICiphernodeRegistry(registry).publishCommittee(\\n e3Id,\\n abi.encode(nodes),\\n publicKey\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setRegistry(address _registry) public onlyOwner {\\n registry = _registry;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function getCommittee(\\n uint256 e3Id\\n ) external view returns (Committee memory) {\\n return committees[e3Id];\\n }\\n}\\n\",\"keccak256\":\"0x764a1b1965828e768fad1a594b858cf25c2edf954137bb49e4de3e474ee150dd\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", - "bytecode": "0x6080346101f457601f610eb938819003918201601f19168301916001600160401b038311848410176101f95780849260409485528339810103126101f457610052602061004b8361020f565b920161020f565b600080516020610e9983398151915254604081901c60ff16159291906001600160401b038116801590816101ec575b60011490816101e2575b1590816101d9575b506101c8576001600160401b03198116600117600080516020610e99833981519152558361019d575b506100c5610299565b6100cd610299565b6100d633610223565b6100de6102c7565b600080546001600160a01b0319166001600160a01b03928316179055600080516020610e7983398151915254811690821603610186575b5061012a575b604051610b7b90816102fe8239f35b68ff000000000000000019600080516020610e998339815191525416600080516020610e99833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a161011b565b610197906101926102c7565b610223565b38610115565b6001600160481b0319166801000000000000000117600080516020610e9983398151915255386100bc565b63f92ee8a960e01b60005260046000fd5b90501538610093565b303b15915061008b565b859150610081565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101f457565b6001600160a01b0316801561028357600080516020610e7983398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff600080516020610e998339815191525460401c16156102b657565b631afcd79f60e31b60005260046000fd5b600080516020610e79833981519152546001600160a01b031633036102e857565b63118cdaa760e01b6000523360045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c90816218449a1461082e5750806329f73b9c1461053a5780632b20a4f614610468578063485cc9551461022e578063715018a6146101955780637b1039991461016f5780638da5cb5b14610129578063a91ee0dc146100ea578063f2fde38b146100bd5763f5e820fd1461008e57600080fd5b346100ba5760203660031901126100ba5760026040602092600435815260018452200154604051908152f35b80fd5b50346100ba5760203660031901126100ba576100e76100da6109e4565b6100e2610ae6565b610a40565b80f35b50346100ba5760203660031901126100ba576001600160a01b0361010c6109e4565b610114610ae6565b166001600160a01b0319600054161760005580f35b50346100ba57806003193601126100ba5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346100ba57806003193601126100ba576001600160a01b036020915416604051908152f35b50346100ba57806003193601126100ba576101ae610ae6565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346100ba5760403660031901126100ba576102486109e4565b602435906001600160a01b0382168203610464577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff81168015908161045c575b6001149081610452575b159081610449575b5061043a5767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556001600160a01b039190846103fb575b506102fd610b2e565b610305610b2e565b61030e33610a40565b610316610ae6565b166001600160a01b031960005416176000556001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b038216036103e9575b5061036b5780f35b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b6103f5906100e2610ae6565b38610363565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055386102f4565b63f92ee8a960e01b8552600485fd5b905015386102ae565b303b1591506102a6565b85915061029c565b8280fd5b50346100ba5760603660031901126100ba5760043536606411610536576001600160a01b03825416330361052757808252600160205263ffffffff600160408420015460201c16610518578152600160205260016040822001602482805b600281106104dd5750505055602060405160018152f35b90919384359063ffffffff8216918281036105145750600583901b91821b63ffffffff90921b1916179360200191906001016104c6565b8480fd5b6334c2a65d60e11b8252600482fd5b6310f5403960e31b8252600482fd5b5080fd5b50346100ba5760603660031901126100ba576024359060043567ffffffffffffffff8311610536573660238401121561053657826004013567ffffffffffffffff811161081a578060051b936040519161059760208701846109c2565b82526020820190602482968201019036821161081657602401915b8183106107f6575050506044359167ffffffffffffffff831161075557366023840112156107555782600401359267ffffffffffffffff84116107e25760405193610607601f8201601f1916602001866109c2565b808552602085019136602483830101116107de57818792602460209301853786010152610632610ae6565b81855260016020526040852090600282019182546107cf5784519067ffffffffffffffff82116107bb576801000000000000000082116107bb578054828255808310610795575b508890885260208820885b83811061077857505050508451902090556001600160a01b0384541660405192604084019060208086015251809152606084019690865b818110610759575050506106dc83869796959603601f1981018552846109c2565b803b1561075557839283610717936107296040519889968795869463d9bbec9560e01b865260048601526060602486015260648501906109ff565b838103600319016044850152906109ff565b03925af180156107485761073a5780f35b610743916109c2565b388180f35b50604051903d90823e3d90fd5b8380fd5b82516001600160a01b03168952602098890198909201916001016106bb565b60019060206001600160a01b038551169401938184015501610684565b8189528260208a2091820191015b8181106107b05750610679565b8981556001016107a3565b634e487b7160e01b88526041600452602488fd5b63632a22bb60e01b8752600487fd5b8680fd5b634e487b7160e01b85526041600452602485fd5b82356001600160a01b03811681036107de578152602092830192016105b2565b8580fd5b634e487b7160e01b83526041600452602483fd5b82346100ba5760203660031901126100ba579061084a81610990565b606081528160408092815161085f83826109c2565b8236823760208201520152600435825260016020528082209080519061088482610990565b80518354808252848652602080872090830191875b81811061097157505050816108af9103826109c2565b8252600281519363ffffffff6001820154818116875260201c1660208601526108d883866109c2565b602084019485520154908083019182528051936020855260a08501935193608060208701528451809152602060c08701950190875b81811061095257505050519084019094905b600282106109365750508293505160808301520390f35b60208060019263ffffffff89511681520196019101909461091f565b82516001600160a01b031687526020968701969092019160010161090d565b82546001600160a01b0316845260209093019260019283019201610899565b6060810190811067ffffffffffffffff8211176109ac57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176109ac57604052565b600435906001600160a01b03821682036109fa57565b600080fd5b919082519283825260005b848110610a2b575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201610a0a565b6001600160a01b03168015610ad0576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610b1957565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610b5d57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081b000a9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c90816218449a1461082e5750806329f73b9c1461053a5780632b20a4f614610468578063485cc9551461022e578063715018a6146101955780637b1039991461016f5780638da5cb5b14610129578063a91ee0dc146100ea578063f2fde38b146100bd5763f5e820fd1461008e57600080fd5b346100ba5760203660031901126100ba5760026040602092600435815260018452200154604051908152f35b80fd5b50346100ba5760203660031901126100ba576100e76100da6109e4565b6100e2610ae6565b610a40565b80f35b50346100ba5760203660031901126100ba576001600160a01b0361010c6109e4565b610114610ae6565b166001600160a01b0319600054161760005580f35b50346100ba57806003193601126100ba5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346100ba57806003193601126100ba576001600160a01b036020915416604051908152f35b50346100ba57806003193601126100ba576101ae610ae6565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346100ba5760403660031901126100ba576102486109e4565b602435906001600160a01b0382168203610464577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff81168015908161045c575b6001149081610452575b159081610449575b5061043a5767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556001600160a01b039190846103fb575b506102fd610b2e565b610305610b2e565b61030e33610a40565b610316610ae6565b166001600160a01b031960005416176000556001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b038216036103e9575b5061036b5780f35b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b6103f5906100e2610ae6565b38610363565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055386102f4565b63f92ee8a960e01b8552600485fd5b905015386102ae565b303b1591506102a6565b85915061029c565b8280fd5b50346100ba5760603660031901126100ba5760043536606411610536576001600160a01b03825416330361052757808252600160205263ffffffff600160408420015460201c16610518578152600160205260016040822001602482805b600281106104dd5750505055602060405160018152f35b90919384359063ffffffff8216918281036105145750600583901b91821b63ffffffff90921b1916179360200191906001016104c6565b8480fd5b6334c2a65d60e11b8252600482fd5b6310f5403960e31b8252600482fd5b5080fd5b50346100ba5760603660031901126100ba576024359060043567ffffffffffffffff8311610536573660238401121561053657826004013567ffffffffffffffff811161081a578060051b936040519161059760208701846109c2565b82526020820190602482968201019036821161081657602401915b8183106107f6575050506044359167ffffffffffffffff831161075557366023840112156107555782600401359267ffffffffffffffff84116107e25760405193610607601f8201601f1916602001866109c2565b808552602085019136602483830101116107de57818792602460209301853786010152610632610ae6565b81855260016020526040852090600282019182546107cf5784519067ffffffffffffffff82116107bb576801000000000000000082116107bb578054828255808310610795575b508890885260208820885b83811061077857505050508451902090556001600160a01b0384541660405192604084019060208086015251809152606084019690865b818110610759575050506106dc83869796959603601f1981018552846109c2565b803b1561075557839283610717936107296040519889968795869463d9bbec9560e01b865260048601526060602486015260648501906109ff565b838103600319016044850152906109ff565b03925af180156107485761073a5780f35b610743916109c2565b388180f35b50604051903d90823e3d90fd5b8380fd5b82516001600160a01b03168952602098890198909201916001016106bb565b60019060206001600160a01b038551169401938184015501610684565b8189528260208a2091820191015b8181106107b05750610679565b8981556001016107a3565b634e487b7160e01b88526041600452602488fd5b63632a22bb60e01b8752600487fd5b8680fd5b634e487b7160e01b85526041600452602485fd5b82356001600160a01b03811681036107de578152602092830192016105b2565b8580fd5b634e487b7160e01b83526041600452602483fd5b82346100ba5760203660031901126100ba579061084a81610990565b606081528160408092815161085f83826109c2565b8236823760208201520152600435825260016020528082209080519061088482610990565b80518354808252848652602080872090830191875b81811061097157505050816108af9103826109c2565b8252600281519363ffffffff6001820154818116875260201c1660208601526108d883866109c2565b602084019485520154908083019182528051936020855260a08501935193608060208701528451809152602060c08701950190875b81811061095257505050519084019094905b600282106109365750508293505160808301520390f35b60208060019263ffffffff89511681520196019101909461091f565b82516001600160a01b031687526020968701969092019160010161090d565b82546001600160a01b0316845260209093019260019283019201610899565b6060810190811067ffffffffffffffff8211176109ac57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176109ac57604052565b600435906001600160a01b03821682036109fa57565b600080fd5b919082519283825260005b848110610a2b575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201610a0a565b6001600160a01b03168015610ad0576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610b1957565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610b5d57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081b000a", - "devdoc": { - "errors": { - "InvalidInitialization()": [ - { - "details": "The contract is already initialized." - } - ], - "NotInitializing()": [ - { - "details": "The contract is not initializing." - } - ], - "OwnableInvalidOwner(address)": [ - { - "details": "The owner is not a valid owner account. (eg. `address(0)`)" - } - ], - "OwnableUnauthorizedAccount(address)": [ - { - "details": "The caller account is not authorized to perform an operation." - } - ] - }, - "events": { - "Initialized(uint64)": { - "details": "Triggered when the contract has been initialized or reinitialized." - } - }, - "kind": "dev", - "methods": { - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 4087, - "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", - "label": "registry", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 4092, - "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", - "label": "committees", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_uint256,t_struct(Committee)4085_storage)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "base": "t_address", - "encoding": "dynamic_array", - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint32)2_storage": { - "base": "t_uint32", - "encoding": "inplace", - "label": "uint32[2]", - "numberOfBytes": "32" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Committee)4085_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct NaiveRegistryFilter.Committee)", - "numberOfBytes": "32", - "value": "t_struct(Committee)4085_storage" - }, - "t_struct(Committee)4085_storage": { - "encoding": "inplace", - "label": "struct NaiveRegistryFilter.Committee", - "members": [ - { - "astId": 4078, - "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", - "label": "nodes", - "offset": 0, - "slot": "0", - "type": "t_array(t_address)dyn_storage" - }, - { - "astId": 4082, - "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", - "label": "threshold", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint32)2_storage" - }, - { - "astId": 4084, - "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", - "label": "publicKey", - "offset": 0, - "slot": "2", - "type": "t_bytes32" - } - ], - "numberOfBytes": "96" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint32": { - "encoding": "inplace", - "label": "uint32", - "numberOfBytes": "4" - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/1560ab6aa11f44088d4445eb3d74156d.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/1560ab6aa11f44088d4445eb3d74156d.json deleted file mode 100644 index 7f1f496ce2..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/1560ab6aa11f44088d4445eb3d74156d.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidInput();\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n requestBlock: block.number,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n uint256 expiresAt = block.timestamp + e3.duration;\n e3s[e3Id].expiration = expiresAt;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, expiresAt, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n\n bytes memory input = e3.inputValidator.validate(msg.sender, data);\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n success = true;\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param requestBlock Block number when the E3 was requested.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256 requestBlock;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the\n /// input of a computation.\n /// @param sender The account that is submitting the input.\n /// @param data The input to be verified.\n /// @return input The decoded, policy-approved application payload.\n function validate(\n address sender,\n bytes memory data\n ) external returns (bytes memory input);\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/3d9e1a948fbfdecab1738e926b737452.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/3d9e1a948fbfdecab1738e926b737452.json deleted file mode 100644 index 40def8bcec..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/3d9e1a948fbfdecab1738e926b737452.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidInput();\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, e3.expiration, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n bytes memory input;\n (input, success) = e3.inputValidator.validate(msg.sender, data);\n require(success, InvalidInput());\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\n /// @param params ABI encoded input parameters.\n /// @return input The input data to be published.\n /// @return success Whether the input parameters are valid.\n function validate(\n address sender,\n bytes memory params\n ) external returns (bytes memory input, bool success);\n}\n" - }, - "contracts/interfaces/IRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" - }, - "contracts/registry/CiphernodeRegistryOwnable.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public enclave;\n uint256 public numCiphernodes;\n LeanIMTData public ciphernodes;\n\n mapping(uint256 e3Id => IRegistryFilter filter) public filters;\n mapping(uint256 e3Id => uint256 root) public roots;\n mapping(uint256 e3Id => bytes32 publicKeyHash) public publicKeyHashes;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyRequested();\n error CommitteeAlreadyPublished();\n error OnlyFilter();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address node);\n error OnlyEnclave();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyEnclave() {\n require(msg.sender == enclave, OnlyEnclave());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _enclave) public initializer {\n __Ownable_init(msg.sender);\n setEnclave(_enclave);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external onlyEnclave returns (bool success) {\n require(\n filters[e3Id] == IRegistryFilter(address(0)),\n CommitteeAlreadyRequested()\n );\n filters[e3Id] = IRegistryFilter(filter);\n roots[e3Id] = root();\n\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\n emit CommitteeRequested(e3Id, filter, threshold);\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n bytes calldata,\n bytes calldata publicKey\n ) external {\n // only to be published by the filter\n require(address(filters[e3Id]) == msg.sender, OnlyFilter());\n\n publicKeyHashes[e3Id] = keccak256(publicKey);\n emit CommitteePublished(e3Id, publicKey);\n }\n\n function addCiphernode(address node) external onlyOwner {\n uint160 ciphernode = uint160(node);\n ciphernodes._insert(ciphernode);\n numCiphernodes++;\n emit CiphernodeAdded(\n node,\n ciphernodes._indexOf(ciphernode),\n numCiphernodes,\n ciphernodes.size\n );\n }\n\n function removeCiphernode(\n address node,\n uint256[] calldata siblingNodes\n ) external onlyOwner {\n uint160 ciphernode = uint160(node);\n uint256 index = ciphernodes._indexOf(ciphernode);\n ciphernodes._remove(ciphernode, siblingNodes);\n numCiphernodes--;\n emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setEnclave(address _enclave) public onlyOwner {\n enclave = _enclave;\n emit EnclaveSet(_enclave);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash) {\n publicKeyHash = publicKeyHashes[e3Id];\n require(publicKeyHash != bytes32(0), CommitteeNotPublished());\n }\n\n function isCiphernodeEligible(address node) external view returns (bool) {\n return isEnabled(node);\n }\n\n function isEnabled(address node) public view returns (bool) {\n return ciphernodes._has(uint160(node));\n }\n\n function root() public view returns (uint256) {\n return (ciphernodes._root());\n }\n\n function rootAt(uint256 e3Id) public view returns (uint256) {\n return roots[e3Id];\n }\n\n function getFilter(uint256 e3Id) public view returns (IRegistryFilter) {\n return filters[e3Id];\n }\n\n function treeSize() public view returns (uint256) {\n return ciphernodes.size;\n }\n}\n" - }, - "contracts/registry/NaiveRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes32 publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _registry) {\n initialize(_owner, _registry);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\n committees[e3Id].threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished());\n committee.nodes = nodes;\n committee.publicKey = keccak256(publicKey);\n ICiphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getCommittee(\n uint256 e3Id\n ) external view returns (Committee memory) {\n return committees[e3Id];\n }\n}\n" - }, - "contracts/test/MockCiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\n\ncontract MockCiphernodeRegistry is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256 e3Id) external pure returns (bytes32) {\n if (e3Id == type(uint256).max) {\n return bytes32(0);\n } else {\n return keccak256(abi.encode(e3Id));\n }\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n\ncontract MockCiphernodeRegistryEmptyKey is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256) external pure returns (bytes32) {\n return bytes32(0);\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/MockE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IE3Program, IInputValidator } from \"../interfaces/IE3Program.sol\";\n\ncontract MockE3Program is IE3Program {\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\n\n bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256(\"fhe.rs:BFV\");\n\n IInputValidator private storageInputValidator;\n\n constructor(IInputValidator _inputValidator) {\n storageInputValidator = _inputValidator;\n }\n\n function setInputValidator(IInputValidator _inputValidator) external {\n storageInputValidator = _inputValidator;\n }\n\n function validate(\n uint256,\n uint256,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n )\n external\n view\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator)\n {\n require(\n computeProviderParams.length == 32,\n invalidParams(e3ProgramParams, computeProviderParams)\n );\n\n inputValidator = storageInputValidator;\n encryptionSchemeId = ENCRYPTION_SCHEME_ID;\n }\n\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n if (data.length > 0) success = true;\n }\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/4e50d78ca1d53cbd796603c29498c065.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/4e50d78ca1d53cbd796603c29498c065.json deleted file mode 100644 index ce40210600..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/4e50d78ca1d53cbd796603c29498c065.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidInput();\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n requestBlock: block.number,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, e3.expiration, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n bytes memory input;\n (input, success) = e3.inputValidator.validate(msg.sender, data);\n require(success, InvalidInput());\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param requestBlock Block number when the E3 was requested.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256 requestBlock;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\n /// @param params ABI encoded input parameters.\n /// @return input The input data to be published.\n /// @return success Whether the input parameters are valid.\n function validate(\n address sender,\n bytes memory params\n ) external returns (bytes memory input, bool success);\n}\n" - }, - "contracts/interfaces/IRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" - }, - "contracts/registry/NaiveRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes32 publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address ciphernode);\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n modifier onlyOwnerOrCiphernode() {\n require(\n msg.sender == owner() ||\n ICiphernodeRegistry(registry).isCiphernodeEligible(msg.sender),\n CiphernodeNotEnabled(msg.sender)\n );\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _registry) {\n initialize(_owner, _registry);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\n committees[e3Id].threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished());\n committee.nodes = nodes;\n committee.publicKey = keccak256(publicKey);\n ICiphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getCommittee(\n uint256 e3Id\n ) external view returns (Committee memory) {\n return committees[e3Id];\n }\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/7505270e9ddb813a3809c10e5d95f372.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/7505270e9ddb813a3809c10e5d95f372.json deleted file mode 100644 index 746800b910..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/7505270e9ddb813a3809c10e5d95f372.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@excubiae/contracts/checker/AdvancedChecker.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {IAdvancedChecker, Check, CheckStatus} from \"../interfaces/IAdvancedChecker.sol\";\nimport {Clone} from \"../proxy/Clone.sol\";\n\n/// @title AdvancedChecker\n/// @notice Abstract contract for multi-phase validation (PRE, MAIN, POST).\n/// @dev Implements advanced validation by routing checks to appropriate phases.\n/// This is intended to be extended for complex validation systems.\nabstract contract AdvancedChecker is Clone, IAdvancedChecker {\n /// @notice Validates a subject's evidence for a specific check phase.\n /// @dev External entry point for validation checks, delegating logic to `_check`.\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @param checkType The phase of validation to execute (PRE, MAIN, POST).\n /// @return checked Boolean indicating whether the validation passed.\n function check(\n address subject,\n bytes calldata evidence,\n Check checkType\n ) external view override returns (bool checked) {\n return _check(subject, evidence, checkType);\n }\n\n /// @notice Core validation logic dispatcher.\n /// @dev Routes validation calls to specific phase methods (_checkPre, _checkMain, _checkPost).\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @param checkType The phase of validation to execute.\n /// @return checked Boolean indicating whether the validation passed.\n function _check(address subject, bytes calldata evidence, Check checkType) internal view returns (bool checked) {\n if (checkType == Check.PRE) {\n return _checkPre(subject, evidence);\n }\n\n if (checkType == Check.POST) {\n return _checkPost(subject, evidence);\n }\n\n return _checkMain(subject, evidence);\n }\n\n /// @notice Pre-condition validation logic.\n /// @dev Derived contracts should override this to implement pre-check validation.\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @return checked Boolean indicating whether the validation passed.\n function _checkPre(address subject, bytes calldata evidence) internal view virtual returns (bool checked) {}\n\n /// @notice Main validation logic.\n /// @dev Derived contracts should override this to implement main check validation.\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @return checked Boolean indicating whether the validation passed.\n function _checkMain(address subject, bytes calldata evidence) internal view virtual returns (bool checked) {}\n\n /// @notice Post-condition validation logic.\n /// @dev Derived contracts should override this to implement post-check validation.\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @return checked Boolean indicating whether the validation passed.\n function _checkPost(address subject, bytes calldata evidence) internal view virtual returns (bool checked) {}\n}\n" - }, - "@excubiae/contracts/interfaces/IAdvancedChecker.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n/// @title Check\n/// @notice Enum representing validation phases.\n/// @dev Used to identify the specific validation phase in multi-phase systems.\n/// @dev The PRE and POST checks are optional and may be skipped based on contract settings.\nenum Check {\n /// Pre-condition validation.\n PRE,\n /// Primary validation.\n MAIN,\n /// Post-condition validation.\n POST\n}\n\n/// @notice Tracks the status of validation checks.\n/// @dev Used in AdvancedPolicy to maintain the state of multi-phase checks.\nstruct CheckStatus {\n /// @notice Indicates whether the pre-condition check has been completed.\n bool pre;\n /// @notice Tracks the number of main checks completed.\n uint8 main;\n /// @notice Indicates whether the post-condition check has been completed.\n bool post;\n}\n\n/// @title IAdvancedChecker\n/// @notice Interface defining multi-phase validation capabilities.\n/// @dev Supports PRE, MAIN, and POST validation phases.\ninterface IAdvancedChecker {\n /// @notice Validates a subject for a specific check phase.\n /// @dev Implementations should route to appropriate phase-specific logic.\n /// @param subject The address to validate.\n /// @param evidence Custom validation data.\n /// @param checkType The phase of validation to execute (PRE, MAIN, POST).\n /// @return checked Boolean indicating whether the validation passed.\n function check(address subject, bytes calldata evidence, Check checkType) external view returns (bool checked);\n}\n" - }, - "@excubiae/contracts/interfaces/IAdvancedPolicy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {IPolicy} from \"./IPolicy.sol\";\nimport {Check} from \"./IAdvancedChecker.sol\";\n\n/// @title IAdvancedPolicy\n/// @notice Extends IPolicy with support for multi-phase validation checks (pre, main, post).\n/// @dev Adds granular error reporting and event logging for advanced enforcement scenarios.\ninterface IAdvancedPolicy is IPolicy {\n /// @notice Error thrown when multiple main checks are attempted but not allowed.\n error MainCheckAlreadyEnforced();\n\n /// @notice Error thrown when a main check is attempted without a prior pre-check.\n error PreCheckNotEnforced();\n\n /// @notice Error thrown when a post-check is attempted without a prior main check.\n error MainCheckNotEnforced();\n\n /// @notice Error thrown when a pre-check is attempted while pre-checks are skipped.\n error CannotPreCheckWhenSkipped();\n\n /// @notice Error thrown when a post-check is attempted while post-checks are skipped.\n error CannotPostCheckWhenSkipped();\n\n /// @notice Emitted when a subject successfully passes a validation check.\n /// @param subject Address that passed the validation.\n /// @param guarded Address of the protected contract.\n /// @param evidence Custom validation data.\n /// @param checkType The type of check performed (PRE, MAIN, POST).\n event Enforced(address indexed subject, address indexed guarded, bytes evidence, Check checkType);\n\n /// @notice Enforces a specific phase of the policy check on a given subject.\n /// @dev Delegates validation logic to the corresponding phase's check method.\n /// @param subject Address to validate.\n /// @param evidence Custom validation data.\n /// @param checkType The type of check performed (PRE, MAIN, POST).\n function enforce(address subject, bytes calldata evidence, Check checkType) external;\n}\n" - }, - "@excubiae/contracts/interfaces/IClone.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n/// @title IClone\n/// @notice Interface for cloneable contracts with initialization logic.\n/// @dev Supports minimal proxy pattern and appended bytes retrieval.\ninterface IClone {\n /// @notice Error thrown when the clone is already initialized.\n error AlreadyInitialized();\n\n /// @notice Initializes the clone contract.\n /// @dev Typically used for setting up state or configuration data.\n function initialize() external;\n\n /// @notice Retrieves appended bytes from the clone's runtime bytecode.\n /// @return Appended bytes passed during the clone's creation.\n function getAppendedBytes() external returns (bytes memory);\n}\n" - }, - "@excubiae/contracts/interfaces/IFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n/// @title IFactory\n/// @notice Base interface for factory contracts responsible for deploying minimal proxy clones.\n/// @dev Provides methods for clone deployment and related events.\ninterface IFactory {\n /// @notice Emitted when a new clone contract is successfully deployed.\n /// @param clone Address of the deployed clone contract.\n event CloneDeployed(address indexed clone);\n}\n" - }, - "@excubiae/contracts/interfaces/IPolicy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n/// @title IPolicy\n/// @notice Core interface for managing policies that protect specific contracts.\n/// @dev Provides methods for setting and retrieving the protected contract and enforcing checks.\ninterface IPolicy {\n /// @notice Emitted when the guarded contract is successfully set.\n /// @param guarded Address of the protected contract.\n event TargetSet(address indexed guarded);\n\n /// @notice Error thrown when a zero address is provided where not allowed.\n error ZeroAddress();\n\n /// @notice Error thrown when a validation check fails.\n error UnsuccessfulCheck();\n\n /// @notice Error thrown when the guarded contract is not set.\n error TargetNotSet();\n\n /// @notice Error thrown when a function is restricted to calls from the guarded contract.\n error TargetOnly();\n\n /// @notice Error thrown when attempting to set the guarded more than once.\n error TargetAlreadySet();\n\n /// @notice Retrieves the policy trait identifier.\n /// @dev This is typically used to distinguish policy implementations (e.g., \"Semaphore\").\n /// @return The policy trait string.\n function trait() external pure returns (string memory);\n\n /// @notice Sets the contract address to be protected by this policy.\n /// @dev This function is restricted to the owner and can only be called once.\n /// @param _guarded The address of the protected contract.\n function setTarget(address _guarded) external;\n}\n" - }, - "@excubiae/contracts/policy/AdvancedPolicy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {IAdvancedPolicy, Check} from \"../interfaces/IAdvancedPolicy.sol\";\nimport {AdvancedChecker} from \"../checker/AdvancedChecker.sol\";\nimport {Policy} from \"./Policy.sol\";\n\n/// @title AdvancedPolicy\n/// @notice Implements multi-stage policy checks with pre, main, and post validation stages.\n/// @dev Extends Policy and provides advanced enforcement logic with an AdvancedChecker.\nabstract contract AdvancedPolicy is IAdvancedPolicy, Policy {\n /// @notice Reference to the AdvancedChecker contract used for validation.\n AdvancedChecker public ADVANCED_CHECKER;\n\n /// @notice Controls whether pre-condition checks are required.\n bool public SKIP_PRE;\n\n /// @notice Controls whether post-condition checks are required.\n bool public SKIP_POST;\n\n /// @notice Initializes the contract with appended bytes data for configuration.\n /// @dev Decodes AdvancedChecker address and sets the owner.\n function _initialize() internal virtual override {\n super._initialize();\n\n bytes memory data = _getAppendedBytes();\n (address sender, address advCheckerAddr, bool skipPre, bool skipPost) = abi.decode(\n data,\n (address, address, bool, bool)\n );\n\n _transferOwnership(sender);\n\n ADVANCED_CHECKER = AdvancedChecker(advCheckerAddr);\n SKIP_PRE = skipPre;\n SKIP_POST = skipPost;\n }\n\n /// @notice Enforces a multi-stage policy check.\n /// @dev Handles pre, main, and post validation stages. Only callable by the guarded contract.\n /// @param subject Address to enforce the policy on.\n /// @param evidence Custom validation data.\n /// @param checkType The type of check performed (PRE, MAIN, POST).\n function enforce(address subject, bytes calldata evidence, Check checkType) external override onlyTarget {\n _enforce(subject, evidence, checkType);\n }\n\n /// @notice Internal implementation of multi-stage enforcement logic.\n /// @param subject Address to enforce the policy on.\n /// @param evidence Custom validation data.\n /// @param checkType The type of check performed (PRE, MAIN, POST).\n function _enforce(address subject, bytes calldata evidence, Check checkType) internal virtual {\n if (checkType == Check.PRE) {\n if (SKIP_PRE) revert CannotPreCheckWhenSkipped();\n } else if (checkType == Check.POST) {\n if (SKIP_POST) revert CannotPostCheckWhenSkipped();\n }\n\n if (!ADVANCED_CHECKER.check(subject, evidence, checkType)) revert UnsuccessfulCheck();\n\n emit Enforced(subject, guarded, evidence, checkType);\n }\n}\n" - }, - "@excubiae/contracts/policy/Policy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {IPolicy} from \"../interfaces/IPolicy.sol\";\nimport {Clone} from \"../proxy/Clone.sol\";\n\n/// @title Policy\n/// @notice Abstract base contract for implementing policies to enforce access control.\n/// @dev Extends Clone and Ownable to provide policy initialization, ownership, and guarded management.\nabstract contract Policy is Clone, IPolicy, Ownable(msg.sender) {\n /// @notice The address of the contract being protected by the policy.\n /// @dev Can only be set once by the owner.\n address public guarded;\n\n /// @notice Modifier to restrict access to only the guarded contract.\n modifier onlyTarget() {\n if (msg.sender != guarded) revert TargetOnly();\n _;\n }\n\n /// @notice Initializes the contract and sets the owner.\n /// @dev Overrides Clone's `_initialize` to include owner setup.\n function _initialize() internal virtual override {\n super._initialize();\n\n // Sets the factory as the initial owner.\n _transferOwnership(msg.sender);\n }\n\n /// @notice Sets the contract address to be protected by this policy.\n /// @dev Can only be called once by the owner.\n /// @param _guarded The contract address to protect.\n function setTarget(address _guarded) external virtual onlyOwner {\n if (_guarded == address(0)) revert ZeroAddress();\n if (guarded != address(0)) revert TargetAlreadySet();\n\n guarded = _guarded;\n emit TargetSet(_guarded);\n }\n}\n" - }, - "@excubiae/contracts/proxy/Clone.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {IClone} from \"../interfaces/IClone.sol\";\nimport {LibClone} from \"solady/src/utils/LibClone.sol\";\n\n/// @title Clone\n/// @notice Abstract base contract for creating cloneable contracts with initialization logic.\n/// @dev Provides utilities for managing clone initialization and retrieving appended arguments.\nabstract contract Clone is IClone {\n /// @notice Tracks whether the clone has been initialized.\n /// @dev Prevents re-initialization through the `_initialize` function.\n bool public initialized;\n\n /// @notice Initializes the clone.\n /// @dev Calls the internal `_initialize` function to set up the clone.\n /// Reverts if the clone is already initialized.\n function initialize() external {\n _initialize();\n }\n\n /// @notice Retrieves appended arguments from the clone.\n /// @dev Leverages `LibClone` to extract arguments from the clone's runtime bytecode.\n /// @return appendedBytes The appended bytes extracted from the clone.\n function getAppendedBytes() external returns (bytes memory appendedBytes) {\n return _getAppendedBytes();\n }\n\n /// @notice Internal function to initialize the clone.\n /// @dev Must be overridden by derived contracts to implement custom initialization logic.\n /// Reverts if the clone has already been initialized.\n function _initialize() internal virtual {\n if (initialized) revert AlreadyInitialized();\n initialized = true;\n }\n\n /// @notice Internal function to retrieve appended arguments from the clone.\n /// @dev Uses `LibClone` utility to extract the arguments.\n /// @return appendedBytes The appended bytes extracted from the clone.\n function _getAppendedBytes() internal virtual returns (bytes memory appendedBytes) {\n return LibClone.argsOnClone(address(this));\n }\n}\n" - }, - "@excubiae/contracts/proxy/Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport {LibClone} from \"solady/src/utils/LibClone.sol\";\nimport {IFactory} from \"../interfaces/IFactory.sol\";\n\n/// @title Factory\n/// @notice Abstract base contract for deploying clone contracts.\n/// @dev Provides functionality to deploy minimal proxy contracts using a standard implementation address.\nabstract contract Factory is IFactory {\n /// @notice Address of the implementation contract used for cloning.\n /// @dev This address is immutable and defines the logic contract for all clones deployed by the factory.\n address public immutable IMPLEMENTATION;\n\n /// @notice Initializes the factory with the implementation contract address.\n /// @param _implementation Address of the logic contract to use for clones.\n constructor(address _implementation) {\n IMPLEMENTATION = _implementation;\n }\n\n /// @notice Deploys a new clone contract.\n /// @dev Uses `LibClone` to deploy a minimal proxy contract with appended initialization data.\n /// Emits a `CloneDeployed` event upon successful deployment.\n /// @param data Initialization data to append to the clone.\n /// @return clone Address of the deployed clone contract.\n function _deploy(bytes memory data) internal returns (address clone) {\n clone = LibClone.clone(IMPLEMENTATION, data);\n\n emit CloneDeployed(clone);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@openzeppelin/contracts/access/Ownable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { IEnclavePolicy } from \"./interfaces/IEnclavePolicy.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport {\n IAdvancedPolicy\n} from \"@excubiae/contracts/interfaces/IAdvancedPolicy.sol\";\nimport { Check } from \"@excubiae/contracts/interfaces/IAdvancedChecker.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IAdvancedPolicy inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n // Excubiae Errors\n error UnsuccessfulCheck();\n error MainCalledTooManyTimes();\n\n // Excubiae Events\n event CloneDeployed(address indexed clone);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IEnclavePolicy inputValidator) = e3Program\n .validate(\n e3Id,\n seed,\n e3ProgramParams,\n computeProviderParams\n );\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n requestBlock: block.number,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, e3.expiration, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n\n e3.inputValidator.enforce(msg.sender, data, Check.MAIN);\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(data)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n success = true;\n\n emit InputPublished(e3Id, data, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\ninterface IComputeProvider {\n /// @notice This function should be called by the Enclave contract to validate the compute provider parameters.\n /// @param params ABI encoded compute provider parameters.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata params\n ) external returns (IDecryptionVerifier decryptionVerifier);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclavePolicy } from \"./IEnclavePolicy.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param requestBlock Block number when the E3 was requested.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256 requestBlock;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IEnclavePolicy inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclavePolicy } from \"./IEnclavePolicy.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IEnclavePolicy inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IEnclaveChecker.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\n// solhint-disable no-empty-blocks\n\nimport {\n IAdvancedChecker\n} from \"@excubiae/contracts/interfaces/IAdvancedChecker.sol\";\n\n/// @title IEnclaveChecker.\n/// @notice Extends IAdvancedChecker\ninterface IEnclaveChecker is IAdvancedChecker {}\n" - }, - "contracts/interfaces/IEnclavePolicy.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\n// solhint-disable no-empty-blocks\n\nimport {\n IAdvancedPolicy\n} from \"@excubiae/contracts/interfaces/IAdvancedPolicy.sol\";\n\n/// @title IEnclavePolicy.\n/// @notice Extends IPolicy with multi-phase validation capabilities.\ninterface IEnclavePolicy is IAdvancedPolicy {}\n" - }, - "contracts/interfaces/IEnclavePolicyFactory.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IFactory } from \"@excubiae/contracts/interfaces/IFactory.sol\";\n\ninterface IEnclavePolicyFactory is IFactory {\n function deploy(\n address _checkerAddr,\n uint8 _inputLimit\n ) external returns (address clone);\n}\n" - }, - "contracts/interfaces/IRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" - }, - "contracts/registry/CiphernodeRegistryOwnable.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public enclave;\n uint256 public numCiphernodes;\n LeanIMTData public ciphernodes;\n\n mapping(uint256 e3Id => IRegistryFilter filter) public filters;\n mapping(uint256 e3Id => uint256 root) public roots;\n mapping(uint256 e3Id => bytes32 publicKeyHash) public publicKeyHashes;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyRequested();\n error CommitteeAlreadyPublished();\n error OnlyFilter();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address node);\n error OnlyEnclave();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyEnclave() {\n require(msg.sender == enclave, OnlyEnclave());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _enclave) public initializer {\n __Ownable_init(msg.sender);\n setEnclave(_enclave);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external onlyEnclave returns (bool success) {\n require(\n filters[e3Id] == IRegistryFilter(address(0)),\n CommitteeAlreadyRequested()\n );\n filters[e3Id] = IRegistryFilter(filter);\n roots[e3Id] = root();\n\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\n emit CommitteeRequested(e3Id, filter, threshold);\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n bytes calldata,\n bytes calldata publicKey\n ) external {\n // only to be published by the filter\n require(address(filters[e3Id]) == msg.sender, OnlyFilter());\n\n publicKeyHashes[e3Id] = keccak256(publicKey);\n emit CommitteePublished(e3Id, publicKey);\n }\n\n function addCiphernode(address node) external onlyOwner {\n uint160 ciphernode = uint160(node);\n ciphernodes._insert(ciphernode);\n numCiphernodes++;\n emit CiphernodeAdded(\n node,\n ciphernodes._indexOf(ciphernode),\n numCiphernodes,\n ciphernodes.size\n );\n }\n\n function removeCiphernode(\n address node,\n uint256[] calldata siblingNodes\n ) external onlyOwner {\n uint160 ciphernode = uint160(node);\n uint256 index = ciphernodes._indexOf(ciphernode);\n ciphernodes._remove(ciphernode, siblingNodes);\n numCiphernodes--;\n emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setEnclave(address _enclave) public onlyOwner {\n enclave = _enclave;\n emit EnclaveSet(_enclave);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash) {\n publicKeyHash = publicKeyHashes[e3Id];\n require(publicKeyHash != bytes32(0), CommitteeNotPublished());\n }\n\n function isCiphernodeEligible(address node) external view returns (bool) {\n return isEnabled(node);\n }\n\n function isEnabled(address node) public view returns (bool) {\n return ciphernodes._has(uint160(node));\n }\n\n function root() public view returns (uint256) {\n return (ciphernodes._root());\n }\n\n function rootAt(uint256 e3Id) public view returns (uint256) {\n return roots[e3Id];\n }\n\n function getFilter(uint256 e3Id) public view returns (IRegistryFilter) {\n return filters[e3Id];\n }\n\n function treeSize() public view returns (uint256) {\n return ciphernodes.size;\n }\n}\n" - }, - "contracts/registry/NaiveRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes32 publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address ciphernode);\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n modifier onlyOwnerOrCiphernode() {\n require(\n msg.sender == owner() ||\n ICiphernodeRegistry(registry).isCiphernodeEligible(msg.sender),\n CiphernodeNotEnabled(msg.sender)\n );\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _registry) {\n initialize(_owner, _registry);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\n committees[e3Id].threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished());\n committee.nodes = nodes;\n committee.publicKey = keccak256(publicKey);\n ICiphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getCommittee(\n uint256 e3Id\n ) external view returns (Committee memory) {\n return committees[e3Id];\n }\n}\n" - }, - "contracts/test/MockCiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\n\ncontract MockCiphernodeRegistry is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256 e3Id) external pure returns (bytes32) {\n if (e3Id == type(uint256).max) {\n return bytes32(0);\n } else {\n return keccak256(abi.encode(e3Id));\n }\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n\ncontract MockCiphernodeRegistryEmptyKey is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256) external pure returns (bytes32) {\n return bytes32(0);\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/MockComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport {\n IComputeProvider,\n IDecryptionVerifier\n} from \"../interfaces/IComputeProvider.sol\";\n\ncontract MockComputeProvider is IComputeProvider {\n error invalidParams();\n\n function validate(\n uint256,\n uint256,\n bytes memory params\n ) external pure returns (IDecryptionVerifier decryptionVerifier) {\n require(params.length == 32, invalidParams());\n // solhint-disable no-inline-assembly\n assembly {\n decryptionVerifier := mload(add(params, 32))\n }\n (decryptionVerifier) = abi.decode(params, (IDecryptionVerifier));\n }\n}\n" - }, - "contracts/test/MockDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"../interfaces/IDecryptionVerifier.sol\";\n\ncontract MockDecryptionVerifier is IDecryptionVerifier {\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IE3Program, IEnclavePolicy } from \"../interfaces/IE3Program.sol\";\nimport { IEnclavePolicyFactory } from \"../interfaces/IEnclavePolicyFactory.sol\";\n\ncontract MockE3Program is IE3Program {\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\n error InvalidChecker();\n error InvalidPolicyFactory();\n\n address private constant DO_NOT_OVERRIDE =\n 0x9999999999999999999999999999999999999999;\n bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256(\"fhe.rs:BFV\");\n uint8 public constant INPUT_LIMIT = 100;\n\n IEnclavePolicyFactory private immutable POLICY_FACTORY;\n address private immutable ENCLAVE_CHECKER;\n\n // NOTE: this is primarily for testing\n address private overrideInputValidator = DO_NOT_OVERRIDE;\n\n constructor(IEnclavePolicyFactory _policyFactory, address _enclaveChecker) {\n if (_enclaveChecker == address(0)) {\n revert InvalidChecker();\n }\n\n if (address(_policyFactory) == address(0)) {\n revert InvalidPolicyFactory();\n }\n POLICY_FACTORY = _policyFactory;\n ENCLAVE_CHECKER = _enclaveChecker;\n }\n\n // NOTE: This function is for testing only\n function testOverrideInputValidator(address _inputValidator) external {\n overrideInputValidator = _inputValidator;\n }\n\n function validate(\n uint256,\n uint256,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IEnclavePolicy inputValidator)\n {\n require(\n computeProviderParams.length == 32,\n invalidParams(e3ProgramParams, computeProviderParams)\n );\n\n if (overrideInputValidator == DO_NOT_OVERRIDE) {\n inputValidator = IEnclavePolicy(\n POLICY_FACTORY.deploy(ENCLAVE_CHECKER, INPUT_LIMIT)\n );\n inputValidator.setTarget(msg.sender);\n } else {\n inputValidator = IEnclavePolicy(overrideInputValidator);\n }\n\n encryptionSchemeId = ENCRYPTION_SCHEME_ID;\n }\n\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockInputValidatorChecker.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport {\n AdvancedChecker\n} from \"@excubiae/contracts/checker/AdvancedChecker.sol\";\n\n/// @title MockInputValidatorChecker.\n/// @notice Enclave Input Validator\n/// @dev Extends BaseChecker for input verification.\ncontract MockInputValidatorChecker is AdvancedChecker {\n /// @notice Validates input\n /// @param subject Address to check.\n /// @param evidence mock proof\n /// @return True if proof is valid\n function _checkMain(\n address subject,\n bytes calldata evidence\n ) internal view override returns (bool) {\n super._checkMain(subject, evidence);\n bool success;\n\n if (evidence.length == 3) {\n success = false;\n } else {\n success = true;\n }\n return success;\n }\n}\n" - }, - "contracts/test/MockInputValidatorPolicy.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclavePolicy } from \"../interfaces/IEnclavePolicy.sol\";\nimport { AdvancedPolicy } from \"@excubiae/contracts/policy/AdvancedPolicy.sol\";\nimport {\n AdvancedChecker\n} from \"@excubiae/contracts/checker/AdvancedChecker.sol\";\nimport { Check } from \"@excubiae/contracts/interfaces/IAdvancedChecker.sol\";\n\n/// @title BaseERC721Policy.\n/// @notice Policy enforcer for Enclave Input validation.\n/// @dev Extends BasePolicy with Enclave specific checks.\ncontract MockInputValidatorPolicy is AdvancedPolicy, IEnclavePolicy {\n error MainCalledTooManyTimes();\n\n uint8 public inputLimit;\n mapping(address subject => uint8 count) public enforced;\n\n /// @notice Initializes the contract with appended bytes data for configuration.\n /// @dev Decodes AdvancedChecker address and sets the owner.\n function _initialize() internal virtual override {\n bytes memory data = _getAppendedBytes();\n (address sender, address advCheckerAddr, uint8 _inputLimit) = abi\n .decode(data, (address, address, uint8));\n _transferOwnership(sender);\n\n ADVANCED_CHECKER = AdvancedChecker(advCheckerAddr);\n SKIP_PRE = true;\n SKIP_POST = true;\n inputLimit = _inputLimit;\n }\n\n function _enforce(\n address subject,\n bytes calldata evidence,\n Check checkType\n ) internal override(AdvancedPolicy) onlyTarget {\n uint256 status = enforced[subject];\n if (inputLimit > 0 && status == inputLimit) {\n revert MainCalledTooManyTimes();\n }\n\n super._enforce(subject, evidence, checkType);\n enforced[subject]++;\n }\n\n /// @notice Returns policy identifier.\n /// @return Policy trait string.\n function trait() external pure returns (string memory) {\n return \"MockInputValidator\";\n }\n}\n" - }, - "contracts/test/MockInputValidatorPolicyFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.27;\n\nimport { MockInputValidatorPolicy } from \"./MockInputValidatorPolicy.sol\";\nimport { IEnclavePolicyFactory } from \"../interfaces/IEnclavePolicyFactory.sol\";\nimport { Factory } from \"@excubiae/contracts/proxy/Factory.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/// @title AdvancedERC721PolicyFactory\n/// @notice Factory for deploying minimal proxy instances of AdvancedERC721Policy.\n/// @dev Encodes configuration data for multi-phase policy validation.\ncontract MockInputValidatorPolicyFactory is\n IEnclavePolicyFactory,\n Factory,\n Ownable(msg.sender)\n{\n /// @notice Initializes the factory with the AdvancedERC721Policy implementation.\n constructor() Factory(address(new MockInputValidatorPolicy())) {}\n\n /// @notice Deploys a new AdvancedERC721Policy clone.\n /// @param _checkerAddr Address of the associated checker contract.\n /// @param _inputLimit Maximum number of times that input may be submitted.\n function deploy(\n address _checkerAddr,\n uint8 _inputLimit\n ) public onlyOwner returns (address clone) {\n bytes memory data = abi.encode(msg.sender, _checkerAddr, _inputLimit);\n\n clone = super._deploy(data);\n MockInputValidatorPolicy(clone).initialize();\n }\n}\n" - }, - "contracts/test/MockRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ninterface IRegistry {\n function publishCommittee(\n uint256 e3Id,\n address[] calldata ciphernodes,\n bytes calldata publicKey\n ) external;\n}\n\ncontract MockNaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n Committee storage committee = committees[e3Id];\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\n committee.threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n IRegistry(registry).publishCommittee(e3Id, nodes, publicKey);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\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" - }, - "solady/src/utils/LibClone.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Minimal proxy library.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\n/// @author Minimal proxy by 0age (https://github.com/0age)\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\n/// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)\n///\n/// @dev Minimal proxy:\n/// Although the sw0nt pattern saves 5 gas over the ERC1167 pattern during runtime,\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\n/// which saves 4 gas over the ERC1167 pattern during runtime, and has the smallest bytecode.\n/// - Automatically verified on Etherscan.\n///\n/// @dev Minimal proxy (PUSH0 variant):\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \"_PUSH0\" as\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\n/// Please use with caution.\n/// - Automatically verified on Etherscan.\n///\n/// @dev Clones with immutable args (CWIA):\n/// The implementation of CWIA here does NOT append the immutable args into the calldata\n/// passed into delegatecall. It is simply an ERC1167 minimal proxy with the immutable arguments\n/// appended to the back of the runtime bytecode.\n/// - Uses the identity precompile (0x4) to copy args during deployment.\n///\n/// @dev Minimal ERC1967 proxy:\n/// A minimal ERC1967 proxy, intended to be upgraded with UUPS.\n/// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.\n/// - Automatically verified on Etherscan.\n///\n/// @dev Minimal ERC1967 proxy with immutable args:\n/// - Uses the identity precompile (0x4) to copy args during deployment.\n/// - Automatically verified on Etherscan.\n///\n/// @dev ERC1967I proxy:\n/// A variant of the minimal ERC1967 proxy, with a special code path that activates\n/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the\n/// `implementation` address. The returned implementation is guaranteed to be valid if the\n/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.\n///\n/// @dev ERC1967I proxy with immutable args:\n/// A variant of the minimal ERC1967 proxy, with a special code path that activates\n/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the\n/// - Uses the identity precompile (0x4) to copy args during deployment.\n///\n/// @dev Minimal ERC1967 beacon proxy:\n/// A minimal beacon proxy, intended to be upgraded with an upgradable beacon.\n/// - Automatically verified on Etherscan.\n///\n/// @dev Minimal ERC1967 beacon proxy with immutable args:\n/// - Uses the identity precompile (0x4) to copy args during deployment.\n/// - Automatically verified on Etherscan.\n///\n/// @dev ERC1967I beacon proxy:\n/// A variant of the minimal ERC1967 beacon proxy, with a special code path that activates\n/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the\n/// `implementation` address. The returned implementation is guaranteed to be valid if the\n/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.\n///\n/// @dev ERC1967I proxy with immutable args:\n/// A variant of the minimal ERC1967 beacon proxy, with a special code path that activates\n/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the\n/// - Uses the identity precompile (0x4) to copy args during deployment.\nlibrary LibClone {\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* CONSTANTS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev The keccak256 of deployed code for the clone proxy,\n /// with the implementation set to `address(0)`.\n bytes32 internal constant CLONE_CODE_HASH =\n 0x48db2cfdb2853fce0b464f1f93a1996469459df3ab6c812106074c4106a1eb1f;\n\n /// @dev The keccak256 of deployed code for the PUSH0 proxy,\n /// with the implementation set to `address(0)`.\n bytes32 internal constant PUSH0_CLONE_CODE_HASH =\n 0x67bc6bde1b84d66e267c718ba44cf3928a615d29885537955cb43d44b3e789dc;\n\n /// @dev The keccak256 of deployed code for the ERC-1167 CWIA proxy,\n /// with the implementation set to `address(0)`.\n bytes32 internal constant CWIA_CODE_HASH =\n 0x3cf92464268225a4513da40a34d967354684c32cd0edd67b5f668dfe3550e940;\n\n /// @dev The keccak256 of the deployed code for the ERC1967 proxy.\n bytes32 internal constant ERC1967_CODE_HASH =\n 0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d;\n\n /// @dev The keccak256 of the deployed code for the ERC1967I proxy.\n bytes32 internal constant ERC1967I_CODE_HASH =\n 0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7;\n\n /// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.\n bytes32 internal constant ERC1967_BEACON_PROXY_CODE_HASH =\n 0x14044459af17bc4f0f5aa2f658cb692add77d1302c29fe2aebab005eea9d1162;\n\n /// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.\n bytes32 internal constant ERC1967I_BEACON_PROXY_CODE_HASH =\n 0xf8c46d2793d5aa984eb827aeaba4b63aedcab80119212fce827309788735519a;\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Unable to deploy the clone.\n error DeploymentFailed();\n\n /// @dev The salt must start with either the zero address or `by`.\n error SaltDoesNotStartWith();\n\n /// @dev The ETH transfer has failed.\n error ETHTransferFailed();\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* MINIMAL PROXY OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a clone of `implementation`.\n function clone(address implementation) internal returns (address instance) {\n instance = clone(0, implementation);\n }\n\n /// @dev Deploys a clone of `implementation`.\n /// Deposits `value` ETH during deployment.\n function clone(uint256 value, address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (44 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create(value, 0x0c, 0x35)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n function cloneDeterministic(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = cloneDeterministic(0, implementation, salt);\n }\n\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n /// Deposits `value` ETH during deployment.\n function cloneDeterministic(uint256 value, address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create2(value, 0x0c, 0x35, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the clone of `implementation`.\n function initCode(address implementation) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x40), 0x5af43d3d93803e602a57fd5bf30000000000000000000000)\n mstore(add(c, 0x28), implementation)\n mstore(add(c, 0x14), 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n mstore(c, 0x35) // Store the length.\n mstore(0x40, add(c, 0x60)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`.\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n hash := keccak256(0x0c, 0x35)\n mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the address of the clone of `implementation`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n bytes32 hash = initCodeHash(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a PUSH0 clone of `implementation`.\n function clone_PUSH0(address implementation) internal returns (address instance) {\n instance = clone_PUSH0(0, implementation);\n }\n\n /// @dev Deploys a PUSH0 clone of `implementation`.\n /// Deposits `value` ETH during deployment.\n function clone_PUSH0(uint256 value, address implementation)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 5f | PUSH0 | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 5f | PUSH0 | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (45 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 5f | PUSH0 | 0 | |\n * 5f | PUSH0 | 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | |\n * 5f | PUSH0 | 0 cds 0 0 | |\n * 5f | PUSH0 | 0 0 cds 0 0 | |\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\n * |\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\n * 57 | JUMPI | | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..rds): returndata |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create(value, 0x0e, 0x36)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = cloneDeterministic_PUSH0(0, implementation, salt);\n }\n\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n /// Deposits `value` ETH during deployment.\n function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create2(value, 0x0e, 0x36, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the PUSH0 clone of `implementation`.\n function initCode_PUSH0(address implementation) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x40), 0x5af43d5f5f3e6029573d5ffd5b3d5ff300000000000000000000) // 16\n mstore(add(c, 0x26), implementation) // 20\n mstore(add(c, 0x12), 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n mstore(c, 0x36) // Store the length.\n mstore(0x40, add(c, 0x60)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n hash := keccak256(0x0e, 0x36)\n mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the address of the PUSH0 clone of `implementation`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress_PUSH0(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash_PUSH0(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.\n function clone(address implementation, bytes memory args) internal returns (address instance) {\n instance = clone(0, implementation, args);\n }\n\n /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.\n /// Deposits `value` ETH during deployment.\n function clone(uint256 value, address implementation, bytes memory args)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * ---------------------------------------------------------------------------+\n * CREATION (10 bytes) |\n * ---------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------|\n * 61 runSize | PUSH2 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------|\n * RUNTIME (45 bytes + extraLength) |\n * ---------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------|\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\n * 36 | CALLDATASIZE | cds 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\n * |\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 | [0..cds): calldata |\n * 82 | DUP3 | 0 rds success 0 | [0..cds): calldata |\n * 80 | DUP1 | 0 0 rds success 0 | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success 0 | [0..rds): returndata |\n * 90 | SWAP1 | 0 success | [0..rds): returndata |\n * 3d | RETURNDATASIZE | rds 0 success | [0..rds): returndata |\n * 91 | SWAP2 | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x2b | PUSH1 0x2b | 0x2b success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * ---------------------------------------------------------------------------+\n */\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))\n mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)\n mstore(add(m, 0x14), implementation)\n mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.\n instance := create(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37))\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation`\n /// with immutable arguments encoded in `args` and `salt`.\n function cloneDeterministic(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = cloneDeterministic(0, implementation, args, salt);\n }\n\n /// @dev Deploys a deterministic clone of `implementation`\n /// with immutable arguments encoded in `args` and `salt`.\n function cloneDeterministic(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))\n mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)\n mstore(add(m, 0x14), implementation)\n mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.\n instance := create2(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation`\n /// with immutable arguments encoded in `args` and `salt`.\n /// This method does not revert if the clone has already been deployed.\n function createDeterministicClone(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicClone(0, implementation, args, salt);\n }\n\n /// @dev Deploys a deterministic clone of `implementation`\n /// with immutable arguments encoded in `args` and `salt`.\n /// This method does not revert if the clone has already been deployed.\n function createDeterministicClone(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (bool alreadyDeployed, address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))\n mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)\n mstore(add(m, 0x14), implementation)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.\n // forgefmt: disable-next-item\n mstore(add(m, gt(n, 0xffd2)), add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, keccak256(add(m, 0x0c), add(n, 0x37)))\n mstore(0x01, shl(96, address()))\n mstore(0x15, salt)\n instance := keccak256(0x00, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, add(m, 0x0c), add(n, 0x37), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the clone of `implementation`\n /// using immutable arguments encoded in `args`.\n function initCode(address implementation, bytes memory args)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x57), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(c, 0x37), 0x5af43d82803e903d91602b57fd5bf3)\n mstore(add(c, 0x28), implementation)\n mstore(add(c, 0x14), add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))\n mstore(c, add(0x37, n)) // Store the length.\n mstore(add(c, add(n, 0x57)), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(c, add(n, 0x77))) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`\n /// using immutable arguments encoded in `args`.\n function initCodeHash(address implementation, bytes memory args)\n internal\n pure\n returns (bytes32 hash)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(m, 0x43), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)\n mstore(add(m, 0x14), implementation)\n mstore(m, add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))\n hash := keccak256(add(m, 0x0c), add(n, 0x37))\n }\n }\n\n /// @dev Returns the address of the clone of\n /// `implementation` using immutable arguments encoded in `args`, with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(\n address implementation,\n bytes memory data,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash(implementation, data);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /// @dev Equivalent to `argsOnClone(instance, 0, 2 ** 256 - 1)`.\n function argsOnClone(address instance) internal view returns (bytes memory args) {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x2d))) // Store the length.\n extcodecopy(instance, add(args, 0x20), 0x2d, add(mload(args), 0x20))\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Equivalent to `argsOnClone(instance, start, 2 ** 256 - 1)`.\n function argsOnClone(address instance, uint256 start)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n let n := and(0xffffffffff, sub(extcodesize(instance), 0x2d))\n let l := sub(n, and(0xffffff, mul(lt(start, n), start)))\n extcodecopy(instance, args, add(start, 0x0d), add(l, 0x40))\n mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.\n mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.\n }\n }\n\n /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.\n /// `start` and `end` will be clamped to the range `[0, args.length]`.\n /// The `instance` MUST be deployed via the clone with immutable args functions.\n /// Otherwise, the behavior is undefined.\n /// Out-of-gas reverts if `instance` does not have any code.\n function argsOnClone(address instance, uint256 start, uint256 end)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n if iszero(lt(end, 0xffff)) { end := 0xffff }\n let d := mul(sub(end, start), lt(start, end))\n extcodecopy(instance, args, add(start, 0x0d), add(d, 0x20))\n if iszero(and(0xff, mload(add(args, d)))) {\n let n := sub(extcodesize(instance), 0x2d)\n returndatacopy(returndatasize(), returndatasize(), shr(40, n))\n d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n }\n mstore(args, d) // Store the length.\n mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.\n }\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* MINIMAL ERC1967 PROXY OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n // Note: The ERC1967 proxy here is intended to be upgraded with UUPS.\n // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.\n\n /// @dev Deploys a minimal ERC1967 proxy with `implementation`.\n function deployERC1967(address implementation) internal returns (address instance) {\n instance = deployERC1967(0, implementation);\n }\n\n /// @dev Deploys a minimal ERC1967 proxy with `implementation`.\n /// Deposits `value` ETH during deployment.\n function deployERC1967(uint256 value, address implementation)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * ---------------------------------------------------------------------------------+\n * CREATION (34 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * 73 impl | PUSH20 impl | impl 0 r | [0..runSize): runtime code |\n * 60 slotPos | PUSH1 slotPos | slotPos impl 0 r | [0..runSize): runtime code |\n * 51 | MLOAD | slot impl 0 r | [0..runSize): runtime code |\n * 55 | SSTORE | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------|\n * RUNTIME (61 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..calldatasize): calldata |\n * |\n * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |\n * 7f slot | PUSH32 slot | s 0 cds 0 0 | [0..calldatasize): calldata |\n * 54 | SLOAD | i 0 cds 0 0 | [0..calldatasize): calldata |\n * 5a | GAS | g i 0 cds 0 0 | [0..calldatasize): calldata |\n * f4 | DELEGATECALL | succ | [0..calldatasize): calldata |\n * |\n * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |\n * 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |\n * 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |\n * 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |\n * |\n * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |\n * 60 0x38 | PUSH1 0x38 | dest succ | [0..returndatasize): returndata |\n * 57 | JUMPI | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * fd | REVERT | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..returndatasize): returndata |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * f3 | RETURN | | [0..returndatasize): returndata |\n * ---------------------------------------------------------------------------------+\n */\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x20, 0x6009)\n mstore(0x1e, implementation)\n mstore(0x0a, 0x603d3d8160223d3973)\n instance := create(value, 0x21, 0x5f)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n function deployDeterministicERC1967(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967(0, implementation, salt);\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x20, 0x6009)\n mstore(0x1e, implementation)\n mstore(0x0a, 0x603d3d8160223d3973)\n instance := create2(value, 0x21, 0x5f, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967(address implementation, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967(0, implementation, salt);\n }\n\n /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x20, 0x6009)\n mstore(0x1e, implementation)\n mstore(0x0a, 0x603d3d8160223d3973)\n // Compute and store the bytecode hash.\n mstore(add(m, 0x35), keccak256(0x21, 0x5f))\n mstore(m, shl(88, address()))\n mstore8(m, 0xff) // Write the prefix.\n mstore(add(m, 0x15), salt)\n instance := keccak256(m, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, 0x21, 0x5f, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.\n function initCodeERC1967(address implementation) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x60), 0x3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f300)\n mstore(add(c, 0x40), 0x55f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc)\n mstore(add(c, 0x20), or(shl(24, implementation), 0x600951))\n mstore(add(c, 0x09), 0x603d3d8160223d3973)\n mstore(c, 0x5f) // Store the length.\n mstore(0x40, add(c, 0x80)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.\n function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x20, 0x6009)\n mstore(0x1e, implementation)\n mstore(0x0a, 0x603d3d8160223d3973)\n hash := keccak256(0x21, 0x5f)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the address of the ERC1967 proxy of `implementation`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* MINIMAL ERC1967 PROXY WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.\n function deployERC1967(address implementation, bytes memory args)\n internal\n returns (address instance)\n {\n instance = deployERC1967(0, implementation, args);\n }\n\n /// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.\n /// Deposits `value` ETH during deployment.\n function deployERC1967(uint256 value, address implementation, bytes memory args)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))\n mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x16, 0x6009)\n mstore(0x14, implementation)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.\n mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n instance := create(value, m, add(n, 0x60))\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.\n function deployDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967(0, implementation, args, salt);\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))\n mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x16, 0x6009)\n mstore(0x14, implementation)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.\n mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n instance := create2(value, m, add(n, 0x60), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967(0, implementation, args, salt);\n }\n\n /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (bool alreadyDeployed, address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))\n mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x16, 0x6009)\n mstore(0x14, implementation)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.\n mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, keccak256(m, add(n, 0x60)))\n mstore(0x01, shl(96, address()))\n mstore(0x15, salt)\n instance := keccak256(0x00, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, m, add(n, 0x60), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation` and `args`.\n function initCodeERC1967(address implementation, bytes memory args)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x80), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(c, 0x60), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(add(c, 0x40), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(add(c, 0x20), 0x6009)\n mstore(add(c, 0x1e), implementation)\n mstore(add(c, 0x0a), add(0x61003d3d8160233d3973, shl(56, n)))\n mstore(c, add(n, 0x60)) // Store the length.\n mstore(add(c, add(n, 0x80)), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(c, add(n, 0xa0))) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation` and `args`.\n function initCodeHashERC1967(address implementation, bytes memory args)\n internal\n pure\n returns (bytes32 hash)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(m, 0x60), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n mstore(0x16, 0x6009)\n mstore(0x14, implementation)\n mstore(0x00, add(0x61003d3d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n hash := keccak256(m, add(n, 0x60))\n }\n }\n\n /// @dev Returns the address of the ERC1967 proxy of `implementation`, `args`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967(\n address implementation,\n bytes memory args,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967(implementation, args);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967(address instance) internal view returns (bytes memory args) {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x3d))) // Store the length.\n extcodecopy(instance, add(args, 0x20), 0x3d, add(mload(args), 0x20))\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967(address instance, uint256 start)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n let n := and(0xffffffffff, sub(extcodesize(instance), 0x3d))\n let l := sub(n, and(0xffffff, mul(lt(start, n), start)))\n extcodecopy(instance, args, add(start, 0x1d), add(l, 0x40))\n mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.\n mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.\n }\n }\n\n /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.\n /// `start` and `end` will be clamped to the range `[0, args.length]`.\n /// The `instance` MUST be deployed via the ERC1967 with immutable args functions.\n /// Otherwise, the behavior is undefined.\n /// Out-of-gas reverts if `instance` does not have any code.\n function argsOnERC1967(address instance, uint256 start, uint256 end)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n if iszero(lt(end, 0xffff)) { end := 0xffff }\n let d := mul(sub(end, start), lt(start, end))\n extcodecopy(instance, args, add(start, 0x1d), add(d, 0x20))\n if iszero(and(0xff, mload(add(args, d)))) {\n let n := sub(extcodesize(instance), 0x3d)\n returndatacopy(returndatasize(), returndatasize(), shr(40, n))\n d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n }\n mstore(args, d) // Store the length.\n mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.\n }\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967I PROXY OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n // Note: This proxy has a special code path that activates if `calldatasize() == 1`.\n // This code path skips the delegatecall and directly returns the `implementation` address.\n // The returned implementation is guaranteed to be valid if the keccak256 of the\n // proxy's code is equal to `ERC1967I_CODE_HASH`.\n\n /// @dev Deploys a ERC1967I proxy with `implementation`.\n function deployERC1967I(address implementation) internal returns (address instance) {\n instance = deployERC1967I(0, implementation);\n }\n\n /// @dev Deploys a ERC1967I proxy with `implementation`.\n /// Deposits `value` ETH during deployment.\n function deployERC1967I(uint256 value, address implementation)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * ---------------------------------------------------------------------------------+\n * CREATION (34 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * 73 impl | PUSH20 impl | impl 0 r | [0..runSize): runtime code |\n * 60 slotPos | PUSH1 slotPos | slotPos impl 0 r | [0..runSize): runtime code |\n * 51 | MLOAD | slot impl 0 r | [0..runSize): runtime code |\n * 55 | SSTORE | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------|\n * RUNTIME (82 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * |\n * ::: check calldatasize ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 58 | PC | 1 cds | |\n * 14 | EQ | eqs | |\n * 60 0x43 | PUSH1 0x43 | dest eqs | |\n * 57 | JUMPI | | |\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..calldatasize): calldata |\n * |\n * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |\n * 7f slot | PUSH32 slot | s 0 cds 0 0 | [0..calldatasize): calldata |\n * 54 | SLOAD | i 0 cds 0 0 | [0..calldatasize): calldata |\n * 5a | GAS | g i 0 cds 0 0 | [0..calldatasize): calldata |\n * f4 | DELEGATECALL | succ | [0..calldatasize): calldata |\n * |\n * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |\n * 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |\n * 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |\n * 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |\n * |\n * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |\n * 60 0x3E | PUSH1 0x3E | dest succ | [0..returndatasize): returndata |\n * 57 | JUMPI | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * fd | REVERT | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..returndatasize): returndata |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * f3 | RETURN | | [0..returndatasize): returndata |\n * |\n * ::: implementation , return :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | |\n * 60 0x20 | PUSH1 0x20 | 32 | |\n * 60 0x0F | PUSH1 0x0F | o 32 | |\n * 3d | RETURNDATASIZE | 0 o 32 | |\n * 39 | CODECOPY | | [0..32): implementation slot |\n * 3d | RETURNDATASIZE | 0 | [0..32): implementation slot |\n * 51 | MLOAD | slot | [0..32): implementation slot |\n * 54 | SLOAD | impl | [0..32): implementation slot |\n * 3d | RETURNDATASIZE | 0 impl | [0..32): implementation slot |\n * 52 | MSTORE | | [0..32): implementation address |\n * 59 | MSIZE | 32 | [0..32): implementation address |\n * 3d | RETURNDATASIZE | 0 32 | [0..32): implementation address |\n * f3 | RETURN | | [0..32): implementation address |\n * ---------------------------------------------------------------------------------+\n */\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))\n instance := create(value, 0x0c, 0x74)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.\n function deployDeterministicERC1967I(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967I(0, implementation, salt);\n }\n\n /// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))\n instance := create2(value, 0x0c, 0x74, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967I(address implementation, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967I(0, implementation, salt);\n }\n\n /// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))\n // Compute and store the bytecode hash.\n mstore(add(m, 0x35), keccak256(0x0c, 0x74))\n mstore(m, shl(88, address()))\n mstore8(m, 0xff) // Write the prefix.\n mstore(add(m, 0x15), salt)\n instance := keccak256(m, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, 0x0c, 0x74, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the initialization code of the ERC1967I proxy of `implementation`.\n function initCodeERC1967I(address implementation) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x74), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(c, 0x54), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(c, 0x34), 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(add(c, 0x1d), implementation)\n mstore(add(c, 0x09), 0x60523d8160223d3973)\n mstore(add(c, 0x94), 0)\n mstore(c, 0x74) // Store the length.\n mstore(0x40, add(c, 0xa0)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation`.\n function initCodeHashERC1967I(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))\n hash := keccak256(0x0c, 0x74)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the address of the ERC1967I proxy of `implementation`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967I(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967I(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967I PROXY WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.\n function deployERC1967I(address implementation, bytes memory args) internal returns (address) {\n return deployERC1967I(0, implementation, args);\n }\n\n /// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.\n /// Deposits `value` ETH during deployment.\n function deployERC1967I(uint256 value, address implementation, bytes memory args)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))\n\n mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(add(m, 0x14), implementation)\n mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))\n\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n instance := create(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n))\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`.\n function deployDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967I(0, implementation, args, salt);\n }\n\n /// @dev Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967I(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))\n\n mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(add(m, 0x14), implementation)\n mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))\n\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n instance := create2(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967I(0, implementation, args, salt);\n }\n\n /// @dev Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967I(\n uint256 value,\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (bool alreadyDeployed, address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x75), n))\n mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x16, 0x600f)\n mstore(0x14, implementation)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n mstore(gt(n, 0xffad), add(0xfe6100523d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, keccak256(m, add(n, 0x75)))\n mstore(0x01, shl(96, address()))\n mstore(0x15, salt)\n instance := keccak256(0x00, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, m, add(0x75, n), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the ERC1967I proxy of `implementation` and `args`.\n function initCodeERC1967I(address implementation, bytes memory args)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))\n }\n\n mstore(add(c, 0x75), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(c, 0x55), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(c, 0x35), 0x600f5155f3365814604357363d3d373d3d363d7f360894)\n mstore(add(c, 0x1e), implementation)\n mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))\n mstore(add(c, add(n, 0x95)), 0)\n mstore(c, add(0x75, n)) // Store the length.\n mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation` and `args.\n function initCodeHashERC1967I(address implementation, bytes memory args)\n internal\n pure\n returns (bytes32 hash)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))\n\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(m, 0x75), i), mload(add(add(args, 0x20), i)))\n }\n\n mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)\n mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)\n mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)\n mstore(0x16, 0x600f)\n mstore(0x14, implementation)\n mstore(0x00, add(0x6100523d8160233d3973, shl(56, n)))\n mstore(m, mload(0x16))\n hash := keccak256(m, add(0x75, n))\n }\n }\n\n /// @dev Returns the address of the ERC1967I proxy of `implementation`, `args` with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967I(\n address implementation,\n bytes memory args,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967I(implementation, args);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967I(address instance) internal view returns (bytes memory args) {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x52))) // Store the length.\n extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967I(address instance, uint256 start)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n let n := and(0xffffffffff, sub(extcodesize(instance), 0x52))\n let l := sub(n, and(0xffffff, mul(lt(start, n), start)))\n extcodecopy(instance, args, add(start, 0x32), add(l, 0x40))\n mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.\n /// `start` and `end` will be clamped to the range `[0, args.length]`.\n /// The `instance` MUST be deployed via the ERC1967 with immutable args functions.\n /// Otherwise, the behavior is undefined.\n /// Out-of-gas reverts if `instance` does not have any code.\n function argsOnERC1967I(address instance, uint256 start, uint256 end)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n if iszero(lt(end, 0xffff)) { end := 0xffff }\n let d := mul(sub(end, start), lt(start, end))\n extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))\n if iszero(and(0xff, mload(add(args, d)))) {\n let n := sub(extcodesize(instance), 0x52)\n returndatacopy(returndatasize(), returndatasize(), shr(40, n))\n d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n }\n mstore(args, d) // Store the length.\n mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.\n }\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967 BOOTSTRAP OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n // A bootstrap is a minimal UUPS implementation that allows an ERC1967 proxy\n // pointing to it to be upgraded. The ERC1967 proxy can then be deployed to a\n // deterministic address independent of the implementation:\n // ```\n // address bootstrap = LibClone.erc1967Bootstrap();\n // address instance = LibClone.deployDeterministicERC1967(0, bootstrap, salt);\n // LibClone.bootstrapERC1967(bootstrap, implementation);\n // ```\n\n /// @dev Deploys the ERC1967 bootstrap if it has not been deployed.\n function erc1967Bootstrap() internal returns (address) {\n return erc1967Bootstrap(address(this));\n }\n\n /// @dev Deploys the ERC1967 bootstrap if it has not been deployed.\n function erc1967Bootstrap(address authorizedUpgrader) internal returns (address bootstrap) {\n bytes memory c = initCodeERC1967Bootstrap(authorizedUpgrader);\n bootstrap = predictDeterministicAddress(keccak256(c), bytes32(0), address(this));\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(extcodesize(bootstrap)) {\n if iszero(create2(0, add(c, 0x20), mload(c), 0)) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n }\n\n /// @dev Replaces the implementation at `instance`.\n function bootstrapERC1967(address instance, address implementation) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, implementation)\n if iszero(call(gas(), instance, 0, 0x0c, 0x14, codesize(), 0x00)) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Replaces the implementation at `instance`, and then call it with `data`.\n function bootstrapERC1967AndCall(address instance, address implementation, bytes memory data)\n internal\n {\n /// @solidity memory-safe-assembly\n assembly {\n let n := mload(data)\n mstore(data, implementation)\n if iszero(call(gas(), instance, 0, add(data, 0x0c), add(n, 0x14), codesize(), 0x00)) {\n if iszero(returndatasize()) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n returndatacopy(mload(0x40), 0x00, returndatasize())\n revert(mload(0x40), returndatasize())\n }\n mstore(data, n) // Restore the length of `data`.\n }\n }\n\n /// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.\n function predictDeterministicAddressERC1967Bootstrap() internal view returns (address) {\n return predictDeterministicAddressERC1967Bootstrap(address(this), address(this));\n }\n\n /// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.\n function predictDeterministicAddressERC1967Bootstrap(\n address authorizedUpgrader,\n address deployer\n ) internal pure returns (address) {\n bytes32 hash = initCodeHashERC1967Bootstrap(authorizedUpgrader);\n return predictDeterministicAddress(hash, bytes32(0), deployer);\n }\n\n /// @dev Returns the initialization code of the ERC1967 bootstrap.\n function initCodeERC1967Bootstrap(address authorizedUpgrader)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x80), 0x3d3560601c5af46047573d6000383e3d38fd0000000000000000000000000000)\n mstore(add(c, 0x60), 0xa920a3ca505d382bbc55601436116049575b005b363d3d373d3d601436036014)\n mstore(add(c, 0x40), 0x0338573d3560601c7f360894a13ba1a3210667c828492db98dca3e2076cc3735)\n mstore(add(c, 0x20), authorizedUpgrader)\n mstore(add(c, 0x0c), 0x606880600a3d393df3fe3373)\n mstore(c, 0x72)\n mstore(0x40, add(c, 0xa0))\n }\n }\n\n /// @dev Returns the initialization code hash of the ERC1967 bootstrap.\n function initCodeHashERC1967Bootstrap(address authorizedUpgrader)\n internal\n pure\n returns (bytes32)\n {\n return keccak256(initCodeERC1967Bootstrap(authorizedUpgrader));\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* MINIMAL ERC1967 BEACON PROXY OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n // Note: If you use this proxy, you MUST make sure that the beacon is a\n // valid ERC1967 beacon. This means that the beacon must always return a valid\n // address upon a staticcall to `implementation()`, given sufficient gas.\n // For performance, the deployment operations and the proxy assumes that the\n // beacon is always valid and will NOT validate it.\n\n /// @dev Deploys a minimal ERC1967 beacon proxy.\n function deployERC1967BeaconProxy(address beacon) internal returns (address instance) {\n instance = deployERC1967BeaconProxy(0, beacon);\n }\n\n /// @dev Deploys a minimal ERC1967 beacon proxy.\n /// Deposits `value` ETH during deployment.\n function deployERC1967BeaconProxy(uint256 value, address beacon)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * ---------------------------------------------------------------------------------+\n * CREATION (34 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * 73 beac | PUSH20 beac | beac 0 r | [0..runSize): runtime code |\n * 60 slotPos | PUSH1 slotPos | slotPos beac 0 r | [0..runSize): runtime code |\n * 51 | MLOAD | slot beac 0 r | [0..runSize): runtime code |\n * 55 | SSTORE | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------|\n * RUNTIME (82 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..calldatasize): calldata |\n * |\n * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |\n * |\n * ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 60 0x20 | PUSH1 0x20 | 32 | |\n * 36 | CALLDATASIZE | cds 32 | |\n * 60 0x04 | PUSH1 0x04 | 4 cds 32 | |\n * 36 | CALLDATASIZE | cds 4 cds 32 | |\n * 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32 | |\n * 60 0xe0 | PUSH1 0xe0 | 224 0x5c60da1b cds 4 cds 32 | |\n * 1b | SHL | sel cds 4 cds 32 | |\n * 36 | CALLDATASIZE | cds sel cds 4 cds 32 | |\n * 52 | MSTORE | cds 4 cds 32 | sel |\n * 7f slot | PUSH32 slot | s cds 4 cds 32 | sel |\n * 54 | SLOAD | beac cds 4 cds 32 | sel |\n * 5a | GAS | g beac cds 4 cds 32 | sel |\n * fa | STATICCALL | succ | impl |\n * 50 | POP | | impl |\n * 36 | CALLDATASIZE | cds | impl |\n * 51 | MLOAD | impl | impl |\n * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 5a | GAS | g impl 0 cds 0 0 | [0..calldatasize): calldata |\n * f4 | DELEGATECALL | succ | [0..calldatasize): calldata |\n * |\n * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |\n * 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |\n * 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |\n * 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |\n * |\n * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |\n * 60 0x4d | PUSH1 0x4d | dest succ | [0..returndatasize): returndata |\n * 57 | JUMPI | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * fd | REVERT | | [0..returndatasize): returndata |\n * |\n * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..returndatasize): returndata |\n * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |\n * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |\n * f3 | RETURN | | [0..returndatasize): returndata |\n * ---------------------------------------------------------------------------------+\n */\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))\n instance := create(value, 0x0c, 0x74)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.\n function deployDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967BeaconProxy(0, beacon, salt);\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))\n instance := create2(value, 0x0c, 0x74, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967BeaconProxy(0, beacon, salt);\n }\n\n /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))\n // Compute and store the bytecode hash.\n mstore(add(m, 0x35), keccak256(0x0c, 0x74))\n mstore(m, shl(88, address()))\n mstore8(m, 0xff) // Write the prefix.\n mstore(add(m, 0x15), salt)\n instance := keccak256(m, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, 0x0c, 0x74, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.\n function initCodeERC1967BeaconProxy(address beacon) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x74), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(c, 0x54), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(c, 0x34), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(c, 0x1d), beacon)\n mstore(add(c, 0x09), 0x60523d8160223d3973)\n mstore(add(c, 0x94), 0)\n mstore(c, 0x74) // Store the length.\n mstore(0x40, add(c, 0xa0)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy.\n function initCodeHashERC1967BeaconProxy(address beacon) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))\n hash := keccak256(0x0c, 0x74)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the address of the ERC1967 beacon proxy, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967BeaconProxy(\n address beacon,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967BeaconProxy(beacon);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967 BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a minimal ERC1967 beacon proxy with `args`.\n function deployERC1967BeaconProxy(address beacon, bytes memory args)\n internal\n returns (address instance)\n {\n instance = deployERC1967BeaconProxy(0, beacon, args);\n }\n\n /// @dev Deploys a minimal ERC1967 beacon proxy with `args`.\n /// Deposits `value` ETH during deployment.\n function deployERC1967BeaconProxy(uint256 value, address beacon, bytes memory args)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))\n mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))\n instance := create(value, add(m, 0x16), add(n, 0x75))\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.\n function deployDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967BeaconProxy(0, beacon, args, salt);\n }\n\n /// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967BeaconProxy(\n uint256 value,\n address beacon,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))\n mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))\n instance := create2(value, add(m, 0x16), add(n, 0x75), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967BeaconProxy(0, beacon, args, salt);\n }\n\n /// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967BeaconProxy(\n uint256 value,\n address beacon,\n bytes memory args,\n bytes32 salt\n ) internal returns (bool alreadyDeployed, address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))\n mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, keccak256(add(m, 0x16), add(n, 0x75)))\n mstore(0x01, shl(96, address()))\n mstore(0x15, salt)\n instance := keccak256(0x00, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, add(m, 0x16), add(n, 0x75), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.\n function initCodeERC1967BeaconProxy(address beacon, bytes memory args)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(c, 0x75), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(c, 0x55), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(c, 0x35), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(c, 0x1e), beacon)\n mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))\n mstore(c, add(n, 0x75)) // Store the length.\n mstore(add(c, add(n, 0x95)), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy with `args`.\n function initCodeHashERC1967BeaconProxy(address beacon, bytes memory args)\n internal\n pure\n returns (bytes32 hash)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(m, 0x8b), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)\n mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)\n mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)\n mstore(add(m, 0x14), beacon)\n mstore(m, add(0x6100523d8160233d3973, shl(56, n)))\n hash := keccak256(add(m, 0x16), add(n, 0x75))\n }\n }\n\n /// @dev Returns the address of the ERC1967 beacon proxy with `args`, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967BeaconProxy(\n address beacon,\n bytes memory args,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967BeaconProxy(beacon, args);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967BeaconProxy(address instance) internal view returns (bytes memory args) {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x52))) // Store the length.\n extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967BeaconProxy(address instance, uint256 start)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n let n := and(0xffffffffff, sub(extcodesize(instance), 0x52))\n let l := sub(n, and(0xffffff, mul(lt(start, n), start)))\n extcodecopy(instance, args, add(start, 0x32), add(l, 0x40))\n mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.\n mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.\n }\n }\n\n /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.\n /// `start` and `end` will be clamped to the range `[0, args.length]`.\n /// The `instance` MUST be deployed via the ERC1967 beacon proxy with immutable args functions.\n /// Otherwise, the behavior is undefined.\n /// Out-of-gas reverts if `instance` does not have any code.\n function argsOnERC1967BeaconProxy(address instance, uint256 start, uint256 end)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n if iszero(lt(end, 0xffff)) { end := 0xffff }\n let d := mul(sub(end, start), lt(start, end))\n extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))\n if iszero(and(0xff, mload(add(args, d)))) {\n let n := sub(extcodesize(instance), 0x52)\n returndatacopy(returndatasize(), returndatasize(), shr(40, n))\n d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n }\n mstore(args, d) // Store the length.\n mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.\n }\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967I BEACON PROXY OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n // Note: This proxy has a special code path that activates if `calldatasize() == 1`.\n // This code path skips the delegatecall and directly returns the `implementation` address.\n // The returned implementation is guaranteed to be valid if the keccak256 of the\n // proxy's code is equal to `ERC1967_BEACON_PROXY_CODE_HASH`.\n //\n // If you use this proxy, you MUST make sure that the beacon is a\n // valid ERC1967 beacon. This means that the beacon must always return a valid\n // address upon a staticcall to `implementation()`, given sufficient gas.\n // For performance, the deployment operations and the proxy assumes that the\n // beacon is always valid and will NOT validate it.\n\n /// @dev Deploys a ERC1967I beacon proxy.\n function deployERC1967IBeaconProxy(address beacon) internal returns (address instance) {\n instance = deployERC1967IBeaconProxy(0, beacon);\n }\n\n /// @dev Deploys a ERC1967I beacon proxy.\n /// Deposits `value` ETH during deployment.\n function deployERC1967IBeaconProxy(uint256 value, address beacon)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * ---------------------------------------------------------------------------------+\n * CREATION (34 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * 73 beac | PUSH20 beac | beac 0 r | [0..runSize): runtime code |\n * 60 slotPos | PUSH1 slotPos | slotPos beac 0 r | [0..runSize): runtime code |\n * 51 | MLOAD | slot beac 0 r | [0..runSize): runtime code |\n * 55 | SSTORE | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------|\n * RUNTIME (87 bytes) |\n * ---------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------|\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..calldatasize): calldata |\n * |\n * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |\n * |\n * ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 60 0x20 | PUSH1 0x20 | 32 | |\n * 36 | CALLDATASIZE | cds 32 | |\n * 60 0x04 | PUSH1 0x04 | 4 cds 32 | |\n * 36 | CALLDATASIZE | cds 4 cds 32 | |\n * 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32 | |\n * 60 0xe0 | PUSH1 0xe0 | 224 0x5c60da1b cds 4 cds 32 | |\n * 1b | SHL | sel cds 4 cds 32 | |\n * 36 | CALLDATASIZE | cds sel cds 4 cds 32 | |\n * 52 | MSTORE | cds 4 cds 32 | sel |\n * 7f slot | PUSH32 slot | s cds 4 cds 32 | sel |\n * 54 | SLOAD | beac cds 4 cds 32 | sel |\n * 5a | GAS | g beac cds 4 cds 32 | sel |\n * fa | STATICCALL | succ | impl |\n * ~~~~~~ check calldatasize ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 36 | CALLDATASIZE | cds succ | |\n * 14 | EQ | | impl |\n * 60 0x52 | PUSH1 0x52 | | impl |\n * 57 | JUMPI | | impl |\n * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 36 | CALLDATASIZE | cds | impl |\n * 51 | MLOAD | impl | impl |\n * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n * 5a | GAS | g impl 0 cds 0 0 | [0..calldatasize): calldata |\n * f4 | DELEGATECALL | succ | [0..calldatasize): calldata |\n * |\n * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |\n * 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |\n * 60 0x01 | PUSH1 0x01 | 1 0 rds succ | [0..calldatasize): calldata |\n * 3e | RETURNDATACOPY | succ | [1..returndatasize): returndata |\n * |\n * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |\n * 60 0x52 | PUSH1 0x52 | dest succ | [1..returndatasize): returndata |\n * 57 | JUMPI | | [1..returndatasize): returndata |\n * |\n * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [1..returndatasize): returndata |\n * 60 0x01 | PUSH1 0x01 | 1 rds | [1..returndatasize): returndata |\n * fd | REVERT | | [1..returndatasize): returndata |\n * |\n * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [1..returndatasize): returndata |\n * 3d | RETURNDATASIZE | rds | [1..returndatasize): returndata |\n * 60 0x01 | PUSH1 0x01 | 1 rds | [1..returndatasize): returndata |\n * f3 | RETURN | | [1..returndatasize): returndata |\n * ---------------------------------------------------------------------------------+\n */\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))\n instance := create(value, 0x07, 0x79)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.\n function deployDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967IBeaconProxy(0, beacon, salt);\n }\n\n /// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))\n instance := create2(value, 0x07, 0x79, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967IBeaconProxy(0, beacon, salt);\n }\n\n /// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))\n // Compute and store the bytecode hash.\n mstore(add(m, 0x35), keccak256(0x07, 0x79))\n mstore(m, shl(88, address()))\n mstore8(m, 0xff) // Write the prefix.\n mstore(add(m, 0x15), salt)\n instance := keccak256(m, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, 0x07, 0x79, salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the initialization code of the ERC1967I beacon proxy.\n function initCodeERC1967IBeaconProxy(address beacon) internal pure returns (bytes memory c) {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n mstore(add(c, 0x79), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(c, 0x59), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(c, 0x39), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(c, 0x1d), beacon)\n mstore(add(c, 0x09), 0x60573d8160223d3973)\n mstore(add(c, 0x99), 0)\n mstore(c, 0x79) // Store the length.\n mstore(0x40, add(c, 0xa0)) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the ERC1967I beacon proxy.\n function initCodeHashERC1967IBeaconProxy(address beacon) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))\n hash := keccak256(0x07, 0x79)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero slot.\n }\n }\n\n /// @dev Returns the address of the ERC1967I beacon proxy, with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967IBeaconProxy(\n address beacon,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* ERC1967I BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Deploys a ERC1967I beacon proxy with `args.\n function deployERC1967IBeaconProxy(address beacon, bytes memory args)\n internal\n returns (address instance)\n {\n instance = deployERC1967IBeaconProxy(0, beacon, args);\n }\n\n /// @dev Deploys a ERC1967I beacon proxy with `args.\n /// Deposits `value` ETH during deployment.\n function deployERC1967IBeaconProxy(uint256 value, address beacon, bytes memory args)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))\n mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.\n mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))\n instance := create(value, add(m, 0x16), add(n, 0x7a))\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.\n function deployDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)\n internal\n returns (address instance)\n {\n instance = deployDeterministicERC1967IBeaconProxy(0, beacon, args, salt);\n }\n\n /// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n function deployDeterministicERC1967IBeaconProxy(\n uint256 value,\n address beacon,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))\n mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.\n mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))\n instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)\n internal\n returns (bool alreadyDeployed, address instance)\n {\n return createDeterministicERC1967IBeaconProxy(0, beacon, args, salt);\n }\n\n /// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.\n /// Deposits `value` ETH during deployment.\n /// Note: This method is intended for use in ERC4337 factories,\n /// which are expected to NOT revert if the proxy is already deployed.\n function createDeterministicERC1967IBeaconProxy(\n uint256 value,\n address beacon,\n bytes memory args,\n bytes32 salt\n ) internal returns (bool alreadyDeployed, address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n let n := mload(args)\n pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))\n mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(m, 0x14), beacon)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.\n mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, keccak256(add(m, 0x16), add(n, 0x7a)))\n mstore(0x01, shl(96, address()))\n mstore(0x15, salt)\n instance := keccak256(0x00, 0x55)\n for {} 1 {} {\n if iszero(extcodesize(instance)) {\n instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)\n if iszero(instance) {\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n alreadyDeployed := 1\n if iszero(value) { break }\n if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n break\n }\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the initialization code of the ERC1967I beacon proxy with `args`.\n function initCodeERC1967IBeaconProxy(address beacon, bytes memory args)\n internal\n pure\n returns (bytes memory c)\n {\n /// @solidity memory-safe-assembly\n assembly {\n c := mload(0x40)\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x9a), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(c, 0x7a), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(c, 0x5a), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(c, 0x3a), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(c, 0x1e), beacon)\n mstore(add(c, 0x0a), add(0x6100573d8160233d3973, shl(56, n)))\n mstore(add(c, add(n, 0x9a)), 0)\n mstore(c, add(n, 0x7a)) // Store the length.\n mstore(0x40, add(c, add(n, 0xba))) // Allocate memory.\n }\n }\n\n /// @dev Returns the initialization code hash of the ERC1967I beacon proxy with `args`.\n function initCodeHashERC1967IBeaconProxy(address beacon, bytes memory args)\n internal\n pure\n returns (bytes32 hash)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let c := mload(0x40) // Cache the free memory pointer.\n let n := mload(args)\n // Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))\n for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {\n mstore(add(add(c, 0x90), i), mload(add(add(args, 0x20), i)))\n }\n mstore(add(c, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)\n mstore(add(c, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)\n mstore(add(c, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)\n mstore(add(c, 0x14), beacon)\n mstore(c, add(0x6100573d8160233d3973, shl(56, n)))\n hash := keccak256(add(c, 0x16), add(n, 0x7a))\n }\n }\n\n /// @dev Returns the address of the ERC1967I beacon proxy, with `args` and salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddressERC1967IBeaconProxy(\n address beacon,\n bytes memory args,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon, args);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967IBeaconProxy(address instance)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x57))) // Store the length.\n extcodecopy(instance, add(args, 0x20), 0x57, add(mload(args), 0x20))\n mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.\n }\n }\n\n /// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.\n function argsOnERC1967IBeaconProxy(address instance, uint256 start)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n let n := and(0xffffffffff, sub(extcodesize(instance), 0x57))\n let l := sub(n, and(0xffffff, mul(lt(start, n), start)))\n extcodecopy(instance, args, add(start, 0x37), add(l, 0x40))\n mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.\n mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.\n }\n }\n\n /// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.\n /// `start` and `end` will be clamped to the range `[0, args.length]`.\n /// The `instance` MUST be deployed via the ERC1967I beacon proxy with immutable args functions.\n /// Otherwise, the behavior is undefined.\n /// Out-of-gas reverts if `instance` does not have any code.\n function argsOnERC1967IBeaconProxy(address instance, uint256 start, uint256 end)\n internal\n view\n returns (bytes memory args)\n {\n /// @solidity memory-safe-assembly\n assembly {\n args := mload(0x40)\n if iszero(lt(end, 0xffff)) { end := 0xffff }\n let d := mul(sub(end, start), lt(start, end))\n extcodecopy(instance, args, add(start, 0x37), add(d, 0x20))\n if iszero(and(0xff, mload(add(args, d)))) {\n let n := sub(extcodesize(instance), 0x57)\n returndatacopy(returndatasize(), returndatasize(), shr(40, n))\n d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n }\n mstore(args, d) // Store the length.\n mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.\n mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.\n }\n }\n\n /*Ā“:°•.°+.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°•.*•“.*:˚.°*.Ėšā€¢Ā“.°:°•.°+.*•“.*:*/\n /* OTHER OPERATIONS */\n /*.•°:°.Ā“+˚.*°.˚:*.“•*.+°.•°:Ā“*.“•*.•°.•°:°.Ā“:ā€¢ĖšĀ°.*°.˚:*.Ā“+°.•*/\n\n /// @dev Returns `address(0)` if the implementation address cannot be determined.\n function implementationOf(address instance) internal view returns (address result) {\n /// @solidity memory-safe-assembly\n assembly {\n for { extcodecopy(instance, 0x00, 0x00, 0x57) } 1 {} {\n if mload(0x2d) {\n // ERC1967I and ERC1967IBeaconProxy detection.\n if or(\n eq(keccak256(0x00, 0x52), ERC1967I_CODE_HASH),\n eq(keccak256(0x00, 0x57), ERC1967I_BEACON_PROXY_CODE_HASH)\n ) {\n pop(staticcall(gas(), instance, 0x00, 0x01, 0x00, 0x20))\n result := mload(0x0c)\n break\n }\n }\n // 0age clone detection.\n result := mload(0x0b)\n codecopy(0x0b, codesize(), 0x14) // Zeroize the 20 bytes for the address.\n if iszero(xor(keccak256(0x00, 0x2c), CLONE_CODE_HASH)) { break }\n mstore(0x0b, result) // Restore the zeroized memory.\n // CWIA detection.\n result := mload(0x0a)\n codecopy(0x0a, codesize(), 0x14) // Zeroize the 20 bytes for the address.\n if iszero(xor(keccak256(0x00, 0x2d), CWIA_CODE_HASH)) { break }\n mstore(0x0a, result) // Restore the zeroized memory.\n // PUSH0 clone detection.\n result := mload(0x09)\n codecopy(0x09, codesize(), 0x14) // Zeroize the 20 bytes for the address.\n result := shr(xor(keccak256(0x00, 0x2d), PUSH0_CLONE_CODE_HASH), result)\n break\n }\n result := shr(96, result)\n mstore(0x37, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Returns the address when a contract with initialization code hash,\n /// `hash`, is deployed with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, hash)\n mstore(0x01, shl(96, deployer))\n mstore(0x15, salt)\n predicted := keccak256(0x00, 0x55)\n mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n }\n }\n\n /// @dev Requires that `salt` starts with either the zero address or `by`.\n function checkStartsWith(bytes32 salt, address by) internal pure {\n /// @solidity memory-safe-assembly\n assembly {\n // If the salt does not start with the zero address or `by`.\n if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {\n mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Returns the `bytes32` at `offset` in `args`, without any bounds checks.\n /// To load an address, you can use `address(bytes20(argLoad(args, offset)))`.\n function argLoad(bytes memory args, uint256 offset) internal pure returns (bytes32 result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := mload(add(add(args, 0x20), offset))\n }\n }\n}\n" - } - }, - "settings": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/af1a33d80136fdacbd4916512487a8ab.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/af1a33d80136fdacbd4916512487a8ab.json deleted file mode 100644 index 60751689da..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/af1a33d80136fdacbd4916512487a8ab.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidInput();\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n requestBlock: block.number,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, e3.expiration, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n\n bytes memory input = e3.inputValidator.validate(msg.sender, data);\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n success = true;\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param requestBlock Block number when the E3 was requested.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256 requestBlock;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the\n /// input of a computation.\n /// @param sender The account that is submitting the input.\n /// @param data The input to be verified.\n /// @return input The decoded, policy-approved application payload.\n function validate(\n address sender,\n bytes memory data\n ) external returns (bytes memory input);\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/c0f9a30d0a9d62ed2e9527f5f26eeea3.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/c0f9a30d0a9d62ed2e9527f5f26eeea3.json deleted file mode 100644 index b936e0e455..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/c0f9a30d0a9d62ed2e9527f5f26eeea3.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidInput();\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n requestBlock: block.number,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes32 publicKeyHash = ciphernodeRegistry.committeePublicKey(e3Id);\n require(\n keccak256(publicKey) == publicKeyHash,\n CommitteeSelectionFailed()\n );\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = keccak256(publicKey);\n\n emit E3Activated(e3Id, e3.expiration, publicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n bytes memory input;\n (input, success) = e3.inputValidator.validate(msg.sender, data);\n require(success, InvalidInput());\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n keccak256(plaintextOutput),\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutput;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The hash of the public key generated by the given committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKeyHash The hash of the public key of the given committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash);\n}\n" - }, - "contracts/interfaces/IComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\ninterface IComputeProvider {\n /// @notice This function should be called by the Enclave contract to validate the compute provider parameters.\n /// @param params ABI encoded compute provider parameters.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata params\n ) external returns (IDecryptionVerifier decryptionVerifier);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param requestBlock Block number when the E3 was requested.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256 requestBlock;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes32 committeePublicKey;\n bytes32 ciphertextOutput;\n bytes plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n /// @param publicKey Public key of the committee.\n /// @return success True if the E3 was successfully activated.\n function activate(\n uint256 e3Id,\n bytes memory publicKey\n ) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\n /// @param params ABI encoded input parameters.\n /// @return input The input data to be published.\n /// @return success Whether the input parameters are valid.\n function validate(\n address sender,\n bytes memory params\n ) external returns (bytes memory input, bool success);\n}\n" - }, - "contracts/interfaces/IRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" - }, - "contracts/registry/CiphernodeRegistryOwnable.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public enclave;\n uint256 public numCiphernodes;\n LeanIMTData public ciphernodes;\n\n mapping(uint256 e3Id => IRegistryFilter filter) public filters;\n mapping(uint256 e3Id => uint256 root) public roots;\n mapping(uint256 e3Id => bytes32 publicKeyHash) public publicKeyHashes;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyRequested();\n error CommitteeAlreadyPublished();\n error OnlyFilter();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address node);\n error OnlyEnclave();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyEnclave() {\n require(msg.sender == enclave, OnlyEnclave());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _enclave) public initializer {\n __Ownable_init(msg.sender);\n setEnclave(_enclave);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external onlyEnclave returns (bool success) {\n require(\n filters[e3Id] == IRegistryFilter(address(0)),\n CommitteeAlreadyRequested()\n );\n filters[e3Id] = IRegistryFilter(filter);\n roots[e3Id] = root();\n\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\n emit CommitteeRequested(e3Id, filter, threshold);\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n bytes calldata,\n bytes calldata publicKey\n ) external {\n // only to be published by the filter\n require(address(filters[e3Id]) == msg.sender, OnlyFilter());\n\n publicKeyHashes[e3Id] = keccak256(publicKey);\n emit CommitteePublished(e3Id, publicKey);\n }\n\n function addCiphernode(address node) external onlyOwner {\n uint160 ciphernode = uint160(node);\n ciphernodes._insert(ciphernode);\n numCiphernodes++;\n emit CiphernodeAdded(\n node,\n ciphernodes._indexOf(ciphernode),\n numCiphernodes,\n ciphernodes.size\n );\n }\n\n function removeCiphernode(\n address node,\n uint256[] calldata siblingNodes\n ) external onlyOwner {\n uint160 ciphernode = uint160(node);\n uint256 index = ciphernodes._indexOf(ciphernode);\n ciphernodes._remove(ciphernode, siblingNodes);\n numCiphernodes--;\n emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setEnclave(address _enclave) public onlyOwner {\n enclave = _enclave;\n emit EnclaveSet(_enclave);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes32 publicKeyHash) {\n publicKeyHash = publicKeyHashes[e3Id];\n require(publicKeyHash != bytes32(0), CommitteeNotPublished());\n }\n\n function isCiphernodeEligible(address node) external view returns (bool) {\n return isEnabled(node);\n }\n\n function isEnabled(address node) public view returns (bool) {\n return ciphernodes._has(uint160(node));\n }\n\n function root() public view returns (uint256) {\n return (ciphernodes._root());\n }\n\n function rootAt(uint256 e3Id) public view returns (uint256) {\n return roots[e3Id];\n }\n\n function getFilter(uint256 e3Id) public view returns (IRegistryFilter) {\n return filters[e3Id];\n }\n\n function treeSize() public view returns (uint256) {\n return ciphernodes.size;\n }\n}\n" - }, - "contracts/registry/NaiveRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes32 publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address ciphernode);\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n modifier onlyOwnerOrCiphernode() {\n require(\n msg.sender == owner() ||\n ICiphernodeRegistry(registry).isCiphernodeEligible(msg.sender),\n CiphernodeNotEnabled(msg.sender)\n );\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _registry) {\n initialize(_owner, _registry);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\n committees[e3Id].threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(committee.publicKey == bytes32(0), CommitteeAlreadyPublished());\n committee.nodes = nodes;\n committee.publicKey = keccak256(publicKey);\n ICiphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getCommittee(\n uint256 e3Id\n ) external view returns (Committee memory) {\n return committees[e3Id];\n }\n}\n" - }, - "contracts/test/MockCiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\n\ncontract MockCiphernodeRegistry is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256 e3Id) external pure returns (bytes32) {\n if (e3Id == type(uint256).max) {\n return bytes32(0);\n } else {\n return keccak256(abi.encode(e3Id));\n }\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n\ncontract MockCiphernodeRegistryEmptyKey is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256) external pure returns (bytes32) {\n return bytes32(0);\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/MockComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport {\n IComputeProvider,\n IDecryptionVerifier\n} from \"../interfaces/IComputeProvider.sol\";\n\ncontract MockComputeProvider is IComputeProvider {\n error invalidParams();\n\n function validate(\n uint256,\n uint256,\n bytes memory params\n ) external pure returns (IDecryptionVerifier decryptionVerifier) {\n require(params.length == 32, invalidParams());\n // solhint-disable no-inline-assembly\n assembly {\n decryptionVerifier := mload(add(params, 32))\n }\n (decryptionVerifier) = abi.decode(params, (IDecryptionVerifier));\n }\n}\n" - }, - "contracts/test/MockDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"../interfaces/IDecryptionVerifier.sol\";\n\ncontract MockDecryptionVerifier is IDecryptionVerifier {\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IE3Program, IInputValidator } from \"../interfaces/IE3Program.sol\";\n\ncontract MockE3Program is IE3Program {\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\n\n bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256(\"fhe.rs:BFV\");\n\n IInputValidator private storageInputValidator;\n\n constructor(IInputValidator _inputValidator) {\n storageInputValidator = _inputValidator;\n }\n\n function setInputValidator(IInputValidator _inputValidator) external {\n storageInputValidator = _inputValidator;\n }\n\n function validate(\n uint256,\n uint256,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n )\n external\n view\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator)\n {\n require(\n computeProviderParams.length == 32,\n invalidParams(e3ProgramParams, computeProviderParams)\n );\n\n inputValidator = storageInputValidator;\n encryptionSchemeId = ENCRYPTION_SCHEME_ID;\n }\n\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"../interfaces/IInputValidator.sol\";\n\ncontract MockInputValidator is IInputValidator {\n function validate(\n address,\n bytes memory params\n ) external pure returns (bytes memory input, bool success) {\n input = params;\n\n if (input.length == 3) {\n success = false;\n } else {\n success = true;\n }\n }\n}\n" - }, - "contracts/test/MockRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ninterface IRegistry {\n function publishCommittee(\n uint256 e3Id,\n address[] calldata ciphernodes,\n bytes calldata publicKey\n ) external;\n}\n\ncontract MockNaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n Committee storage committee = committees[e3Id];\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\n committee.threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n IRegistry(registry).publishCommittee(e3Id, nodes, publicKey);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/c9b7037486bd8b1125ffad462d6531cb.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/c9b7037486bd8b1125ffad462d6531cb.json deleted file mode 100644 index 4095cc9226..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/c9b7037486bd8b1125ffad462d6531cb.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" - }, - "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" - }, - "@zk-kit/lean-imt.sol/Constants.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" - }, - "@zk-kit/lean-imt.sol/InternalLeanIMT.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {PoseidonT3} from \"poseidon-solidity/PoseidonT3.sol\";\nimport {SNARK_SCALAR_FIELD} from \"./Constants.sol\";\n\nstruct LeanIMTData {\n // Tracks the current number of leaves in the tree.\n uint256 size;\n // Represents the current depth of the tree, which can increase as new leaves are inserted.\n uint256 depth;\n // A mapping from each level of the tree to the node value of the last even position at that level.\n // Used for efficient inserts, updates and root calculations.\n mapping(uint256 => uint256) sideNodes;\n // A mapping from leaf values to their respective indices in the tree.\n // This facilitates checks for leaf existence and retrieval of leaf positions.\n mapping(uint256 => uint256) leaves;\n}\n\nerror WrongSiblingNodes();\nerror LeafGreaterThanSnarkScalarField();\nerror LeafCannotBeZero();\nerror LeafAlreadyExists();\nerror LeafDoesNotExist();\n\n/// @title Lean Incremental binary Merkle tree.\n/// @dev The LeanIMT is an optimized version of the BinaryIMT.\n/// This implementation eliminates the use of zeroes, and make the tree depth dynamic.\n/// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT,\n/// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth,\n/// it is updated based on the number of leaves in the tree. This approach\n/// results in the calculation of significantly fewer hashes, making the tree more efficient.\nlibrary InternalLeanIMT {\n /// @dev Inserts a new leaf into the incremental merkle tree.\n /// The function ensures that the leaf is valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the new leaf to be inserted into the tree.\n /// @return The new hash of the node after the leaf has been inserted.\n function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) {\n if (leaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaf == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = self.size;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // A new insertion can increase a tree's depth by at most 1,\n // and only if the number of leaves supported by the current\n // depth is less than the number of leaves to be supported after insertion.\n if (2 ** treeDepth < index + 1) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n uint256 node = leaf;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n node = PoseidonT3.hash([self.sideNodes[level], node]);\n } else {\n self.sideNodes[level] = node;\n }\n\n unchecked {\n ++level;\n }\n }\n\n self.size = ++index;\n\n self.sideNodes[treeDepth] = node;\n self.leaves[leaf] = index;\n\n return node;\n }\n\n /// @dev Inserts many leaves into the incremental merkle tree.\n /// The function ensures that the leaves are valid according to the\n /// constraints of the tree and then updates the tree's structure accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaves: The values of the new leaves to be inserted into the tree.\n /// @return The root after the leaves have been inserted.\n function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) {\n // Cache tree size to optimize gas\n uint256 treeSize = self.size;\n\n // Check that all the new values are correct to be added.\n for (uint256 i = 0; i < leaves.length; ) {\n if (leaves[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (leaves[i] == 0) {\n revert LeafCannotBeZero();\n } else if (_has(self, leaves[i])) {\n revert LeafAlreadyExists();\n }\n\n self.leaves[leaves[i]] = treeSize + 1 + i;\n\n unchecked {\n ++i;\n }\n }\n\n // Array to save the nodes that will be used to create the next level of the tree.\n uint256[] memory currentLevelNewNodes;\n\n currentLevelNewNodes = leaves;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n // Calculate the depth of the tree after adding the new values.\n // Unlike the 'insert' function, we need a while here as\n // N insertions can increase the tree's depth more than once.\n while (2 ** treeDepth < treeSize + leaves.length) {\n ++treeDepth;\n }\n\n self.depth = treeDepth;\n\n // First index to change in every level.\n uint256 currentLevelStartIndex = treeSize;\n\n // Size of the level used to create the next level.\n uint256 currentLevelSize = treeSize + leaves.length;\n\n // The index where changes begin at the next level.\n uint256 nextLevelStartIndex = currentLevelStartIndex >> 1;\n\n // The size of the next level.\n uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1;\n\n for (uint256 level = 0; level < treeDepth; ) {\n // The number of nodes for the new level that will be created,\n // only the new values, not the entire level.\n uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex;\n uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes);\n for (uint256 i = 0; i < numberOfNewNodes; ) {\n uint256 leftNode;\n\n // Assign the left node using the saved path or the position in the array.\n if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) {\n leftNode = self.sideNodes[level];\n } else {\n leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex];\n }\n\n uint256 rightNode;\n\n // Assign the right node if the value exists.\n if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) {\n rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex];\n }\n\n uint256 parentNode;\n\n // Assign the parent node.\n // If it has a right child the result will be the hash(leftNode, rightNode) if not,\n // it will be the leftNode.\n if (rightNode != 0) {\n parentNode = PoseidonT3.hash([leftNode, rightNode]);\n } else {\n parentNode = leftNode;\n }\n\n nextLevelNewNodes[i] = parentNode;\n\n unchecked {\n ++i;\n }\n }\n\n // Update the `sideNodes` variable.\n // If `currentLevelSize` is odd, the saved value will be the last value of the array\n // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value\n // will be the value before the last one.\n // If it is even and there is only one element, there is no need to save anything because\n // the correct value for this level was already saved before.\n if (currentLevelSize & 1 == 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1];\n } else if (currentLevelNewNodes.length > 1) {\n self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2];\n }\n\n currentLevelStartIndex = nextLevelStartIndex;\n\n // Calculate the next level startIndex value.\n // It is the position of the parent node which is pos/2.\n nextLevelStartIndex >>= 1;\n\n // Update the next array that will be used to calculate the next level.\n currentLevelNewNodes = nextLevelNewNodes;\n\n currentLevelSize = nextLevelSize;\n\n // Calculate the size of the next level.\n // The size of the next level is (currentLevelSize - 1) / 2 + 1.\n nextLevelSize = ((nextLevelSize - 1) >> 1) + 1;\n\n unchecked {\n ++level;\n }\n }\n\n // Update tree size\n self.size = treeSize + leaves.length;\n\n // Update tree root\n self.sideNodes[treeDepth] = currentLevelNewNodes[0];\n\n return currentLevelNewNodes[0];\n }\n\n /// @dev Updates the value of an existing leaf and recalculates hashes\n /// to maintain tree integrity.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf that is to be updated.\n /// @param newLeaf: The new value that will replace the oldLeaf in the tree.\n /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root.\n /// @return The new hash of the updated node after the leaf has been updated.\n function _update(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256 newLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n if (newLeaf >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n } else if (!_has(self, oldLeaf)) {\n revert LeafDoesNotExist();\n } else if (_has(self, newLeaf)) {\n revert LeafAlreadyExists();\n }\n\n uint256 index = _indexOf(self, oldLeaf);\n uint256 node = newLeaf;\n uint256 oldRoot = oldLeaf;\n\n uint256 lastIndex = self.size - 1;\n uint256 i = 0;\n\n // Cache tree depth to optimize gas\n uint256 treeDepth = self.depth;\n\n for (uint256 level = 0; level < treeDepth; ) {\n if ((index >> level) & 1 == 1) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([siblingNodes[i], node]);\n oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]);\n\n unchecked {\n ++i;\n }\n } else {\n if (index >> level != lastIndex >> level) {\n if (siblingNodes[i] >= SNARK_SCALAR_FIELD) {\n revert LeafGreaterThanSnarkScalarField();\n }\n\n node = PoseidonT3.hash([node, siblingNodes[i]]);\n oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]);\n\n unchecked {\n ++i;\n }\n } else {\n self.sideNodes[i] = node;\n }\n }\n\n unchecked {\n ++level;\n }\n }\n\n if (oldRoot != _root(self)) {\n revert WrongSiblingNodes();\n }\n\n self.sideNodes[treeDepth] = node;\n\n if (newLeaf != 0) {\n self.leaves[newLeaf] = self.leaves[oldLeaf];\n }\n\n self.leaves[oldLeaf] = 0;\n\n return node;\n }\n\n /// @dev Removes a leaf from the tree by setting its value to zero.\n /// This function utilizes the update function to set the leaf's value\n /// to zero and update the tree's state accordingly.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param oldLeaf: The value of the leaf to be removed.\n /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal.\n /// @return The new root hash of the tree after the leaf has been removed.\n function _remove(\n LeanIMTData storage self,\n uint256 oldLeaf,\n uint256[] calldata siblingNodes\n ) internal returns (uint256) {\n return _update(self, oldLeaf, 0, siblingNodes);\n }\n\n /// @dev Checks if a leaf exists in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf to check for existence.\n /// @return A boolean value indicating whether the leaf exists in the tree.\n function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) {\n return self.leaves[leaf] != 0;\n }\n\n /// @dev Retrieves the index of a given leaf in the tree.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @param leaf: The value of the leaf whose index is to be found.\n /// @return The index of the specified leaf within the tree. If the leaf is not present, the function\n /// reverts with a custom error.\n function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) {\n if (self.leaves[leaf] == 0) {\n revert LeafDoesNotExist();\n }\n\n return self.leaves[leaf] - 1;\n }\n\n /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the\n /// current tree depth.\n /// @param self: A storage reference to the 'LeanIMTData' struct.\n /// @return The root hash of the tree.\n function _root(LeanIMTData storage self) internal view returns (uint256) {\n return self.sideNodes[self.depth];\n }\n}\n" - }, - "contracts/Enclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IEnclave, E3, IE3Program } from \"./interfaces/IEnclave.sol\";\nimport { ICiphernodeRegistry } from \"./interfaces/ICiphernodeRegistry.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { IDecryptionVerifier } from \"./interfaces/IDecryptionVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData,\n PoseidonT3\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // Mapping of allowed E3 Programs.\n mapping(IE3Program e3Program => bool allowed) public e3Programs;\n\n // Mapping of E3s.\n mapping(uint256 e3Id => E3 e3) public e3s;\n\n // Mapping of input merkle trees.\n mapping(uint256 e3Id => LeanIMTData imt) public inputs;\n\n // Mapping counting the number of inputs for each E3.\n mapping(uint256 e3Id => uint256 inputCount) public inputCounts;\n\n // Mapping of enabled encryption schemes.\n mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier)\n public decryptionVerifiers;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error E3ProgramNotAllowed(IE3Program e3Program);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InvalidEncryptionScheme(bytes32 encryptionSchemeId);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputationRequest(IInputValidator inputValidator);\n error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);\n error InvalidInput();\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _ciphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICiphernodeRegistry _ciphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCiphernodeRegistry(_ciphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program));\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));\n\n (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program\n .validate(e3Id, seed, e3ProgramParams, computeProviderParams);\n IDecryptionVerifier decryptionVerifier = decryptionVerifiers[\n encryptionSchemeId\n ];\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n require(\n address(inputValidator) != address(0),\n InvalidComputationRequest(inputValidator)\n );\n\n e3 = E3({\n seed: seed,\n threshold: threshold,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n encryptionSchemeId: encryptionSchemeId,\n e3Program: e3Program,\n e3ProgramParams: e3ProgramParams,\n inputValidator: inputValidator,\n decryptionVerifier: decryptionVerifier,\n committeePublicKey: hex\"\",\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n ciphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(e3Id, e3, filter, e3Program);\n }\n\n function activate(uint256 e3Id) external returns (bool success) {\n // Note: we could load this into a storage pointer, and do the sets there\n // Requires a mew internal _getter that returns storage\n E3 memory e3 = getE3(e3Id);\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes memory publicKey = ciphernodeRegistry.committeePublicKey(e3Id);\n // Note: This check feels weird\n require(publicKey.length > 0, CommitteeSelectionFailed());\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = publicKey;\n\n emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n bytes memory input;\n (input, success) = e3.inputValidator.validate(msg.sender, data);\n require(success, InvalidInput());\n uint256 inputHash = PoseidonT3.hash(\n [uint256(keccak256(input)), inputCounts[e3Id]]\n );\n\n inputCounts[e3Id]++;\n inputs[e3Id]._insert(inputHash);\n\n emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput == bytes32(0),\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes32 ciphertextOutputHash = keccak256(ciphertextOutput);\n (success) = e3.e3Program.verify(e3Id, ciphertextOutputHash, proof);\n require(success, InvalidOutput(ciphertextOutput));\n e3s[e3Id].ciphertextOutput = ciphertextOutputHash;\n\n emit CiphertextOutputPublished(e3Id, ciphertextOutput);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput != bytes32(0),\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput == bytes32(0),\n PlaintextOutputAlreadyPublished(e3Id)\n );\n bytes32 plaintextOutputHash = keccak256(plaintextOutput);\n (success) = e3.decryptionVerifier.verify(\n e3Id,\n plaintextOutputHash,\n proof\n );\n require(success, InvalidOutput(plaintextOutput));\n e3s[e3Id].plaintextOutput = plaintextOutputHash;\n\n emit PlaintextOutputPublished(e3Id, plaintextOutput);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCiphernodeRegistry(\n ICiphernodeRegistry _ciphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_ciphernodeRegistry) != address(0) &&\n _ciphernodeRegistry != ciphernodeRegistry,\n InvalidCiphernodeRegistry(_ciphernodeRegistry)\n );\n ciphernodeRegistry = _ciphernodeRegistry;\n success = true;\n emit CiphernodeRegistrySet(address(_ciphernodeRegistry));\n }\n\n function enableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(\n !e3Programs[e3Program],\n ModuleAlreadyEnabled(address(e3Program))\n );\n e3Programs[e3Program] = true;\n success = true;\n emit E3ProgramEnabled(e3Program);\n }\n\n function disableE3Program(\n IE3Program e3Program\n ) public onlyOwner returns (bool success) {\n require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program)));\n delete e3Programs[e3Program];\n success = true;\n emit E3ProgramDisabled(e3Program);\n }\n\n function setDecryptionVerifier(\n bytes32 encryptionSchemeId,\n IDecryptionVerifier decryptionVerifier\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifier != IDecryptionVerifier(address(0)) &&\n decryptionVerifiers[encryptionSchemeId] != decryptionVerifier,\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = decryptionVerifier;\n success = true;\n emit EncryptionSchemeEnabled(encryptionSchemeId);\n }\n\n function disableEncryptionScheme(\n bytes32 encryptionSchemeId\n ) public onlyOwner returns (bool success) {\n require(\n decryptionVerifiers[encryptionSchemeId] !=\n IDecryptionVerifier(address(0)),\n InvalidEncryptionScheme(encryptionSchemeId)\n );\n decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier(\n address(0)\n );\n success = true;\n emit EncryptionSchemeDisabled(encryptionSchemeId);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id));\n }\n\n function getInputRoot(uint256 e3Id) public view returns (uint256) {\n require(\n e3s[e3Id].e3Program != IE3Program(address(0)),\n E3DoesNotExist(e3Id)\n );\n return InternalLeanIMT._root(inputs[e3Id]);\n }\n\n function getDecryptionVerifier(\n bytes32 encryptionSchemeId\n ) public view returns (IDecryptionVerifier) {\n return decryptionVerifiers[encryptionSchemeId];\n }\n}\n" - }, - "contracts/interfaces/ICiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface ICiphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a ciphernode is added to the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeAdded(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n /// @notice This event MUST be emitted when a ciphernode is removed from the registry.\n /// @param node Address of the ciphernode.\n /// @param index Index of the ciphernode in the registry.\n /// @param numNodes Number of ciphernodes in the registry.\n /// @param size Size of the registry.\n event CiphernodeRemoved(\n address indexed node,\n uint256 index,\n uint256 numNodes,\n uint256 size\n );\n\n function isCiphernodeEligible(address ciphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The public key generated by the selected committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKey The public key of the committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes memory);\n}\n" - }, - "contracts/interfaces/IComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\ninterface IComputeProvider {\n /// @notice This function should be called by the Enclave contract to validate the compute provider parameters.\n /// @param params ABI encoded compute provider parameters.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata params\n ) external returns (IDecryptionVerifier decryptionVerifier);\n}\n" - }, - "contracts/interfaces/IDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IDecryptionVerifier {\n /// @notice This function should be called by the Enclave contract to verify the\n /// decryption of output of a computation.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutputHash The keccak256 hash of the plaintext output to be verified.\n /// @param proof ABI encoded proof of the given output hash.\n /// @return success Whether or not the plaintextOutputHash was successfully verified.\n function verify(\n uint256 e3Id,\n bytes32 plaintextOutputHash,\n bytes memory proof\n ) external view returns (bool success);\n}\n" - }, - "contracts/interfaces/IE3.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IE3Program } from \"./IE3Program.sol\";\nimport { IDecryptionVerifier } from \"./IDecryptionVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param e3Program Address of the E3 Program contract.\n/// @param computeProvider Address of the compute provider contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param decryptionVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint256 seed;\n uint32[2] threshold;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n bytes32 encryptionSchemeId;\n IE3Program e3Program;\n bytes e3ProgramParams;\n IInputValidator inputValidator;\n IDecryptionVerifier decryptionVerifier;\n bytes committeePublicKey;\n bytes32 ciphertextOutput;\n bytes32 plaintextOutput;\n}\n" - }, - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IEnclave.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { E3, IE3Program } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected.\n /// @param e3Program Address of the Computation module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IE3Program indexed e3Program\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(\n uint256 indexed e3Id,\n bytes data,\n uint256 inputHash,\n uint256 index\n );\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CiphernodeRegistry is set.\n /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract.\n event CiphernodeRegistrySet(address ciphernodeRegistry);\n\n /// @notice The event MUST be emitted any time an encryption scheme is enabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was enabled.\n event EncryptionSchemeEnabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time an encryption scheme is disabled.\n /// @param encryptionSchemeId The ID of the encryption scheme that was disabled.\n event EncryptionSchemeDisabled(bytes32 encryptionSchemeId);\n\n /// @notice This event MUST be emitted any time a E3 Program is enabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramEnabled(IE3Program e3Program);\n\n /// @notice This event MUST be emitted any time a E3 Program is disabled.\n /// @param e3Program The address of the E3 Program.\n event E3ProgramDisabled(IE3Program e3Program);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param e3Program Address of the E3 Program.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IE3Program e3Program,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n function activate(uint256 e3Id) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded output data to verify.\n /// @param proof ABI encoded data to verify the ciphertextOutput.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory ciphertextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n /// @param proof ABI encoded data to verify the plaintextOutput.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory plaintextOutput,\n bytes memory proof\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n\n /// @notice This function returns root of the input merkle tree for a given E3.\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return root The root of the input merkle tree.\n function getInputRoot(uint256 e3Id) external view returns (uint256 root);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\n /// @param params ABI encoded input parameters.\n /// @return input The input data to be published.\n /// @return success Whether the input parameters are valid.\n function validate(\n address sender,\n bytes memory params\n ) external returns (bytes memory input, bool success);\n}\n" - }, - "contracts/interfaces/IRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" - }, - "contracts/registry/CiphernodeRegistryOwnable.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n InternalLeanIMT,\n LeanIMTData\n} from \"@zk-kit/lean-imt.sol/InternalLeanIMT.sol\";\n\ncontract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable {\n using InternalLeanIMT for LeanIMTData;\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public enclave;\n uint256 public numCiphernodes;\n LeanIMTData public ciphernodes;\n\n mapping(uint256 e3Id => IRegistryFilter filter) public filters;\n mapping(uint256 e3Id => uint256 root) public roots;\n mapping(uint256 e3Id => bytes publicKey) public publicKeys;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyRequested();\n error CommitteeAlreadyPublished();\n error OnlyFilter();\n error CommitteeNotPublished();\n error CiphernodeNotEnabled(address node);\n error OnlyEnclave();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyEnclave() {\n require(msg.sender == enclave, OnlyEnclave());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _enclave) public initializer {\n __Ownable_init(msg.sender);\n setEnclave(_enclave);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external onlyEnclave returns (bool success) {\n require(\n filters[e3Id] == IRegistryFilter(address(0)),\n CommitteeAlreadyRequested()\n );\n filters[e3Id] = IRegistryFilter(filter);\n roots[e3Id] = root();\n\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\n emit CommitteeRequested(e3Id, filter, threshold);\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n bytes calldata,\n bytes calldata publicKey\n ) external {\n // only to be published by the filter\n require(address(filters[e3Id]) == msg.sender, OnlyFilter());\n\n publicKeys[e3Id] = publicKey;\n emit CommitteePublished(e3Id, publicKey);\n }\n\n function addCiphernode(address node) external onlyOwner {\n uint160 ciphernode = uint160(node);\n ciphernodes._insert(ciphernode);\n numCiphernodes++;\n emit CiphernodeAdded(\n node,\n ciphernodes._indexOf(ciphernode),\n numCiphernodes,\n ciphernodes.size\n );\n }\n\n function removeCiphernode(\n address node,\n uint256[] calldata siblingNodes\n ) external onlyOwner {\n uint160 ciphernode = uint160(node);\n uint256 index = ciphernodes._indexOf(ciphernode);\n ciphernodes._remove(ciphernode, siblingNodes);\n numCiphernodes--;\n emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setEnclave(address _enclave) public onlyOwner {\n enclave = _enclave;\n emit EnclaveSet(_enclave);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes memory publicKey) {\n publicKey = publicKeys[e3Id];\n require(publicKey.length > 0, CommitteeNotPublished());\n }\n\n function isCiphernodeEligible(address node) external view returns (bool) {\n return isEnabled(node);\n }\n\n function isEnabled(address node) public view returns (bool) {\n return ciphernodes._has(uint160(node));\n }\n\n function root() public view returns (uint256) {\n return (ciphernodes._root());\n }\n\n function rootAt(uint256 e3Id) public view returns (uint256) {\n return roots[e3Id];\n }\n\n function getFilter(uint256 e3Id) public view returns (IRegistryFilter) {\n return filters[e3Id];\n }\n\n function treeSize() public view returns (uint256) {\n return ciphernodes.size;\n }\n}\n" - }, - "contracts/registry/NaiveRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _registry) {\n initialize(_owner, _registry);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n require(committees[e3Id].threshold[1] == 0, CommitteeAlreadyExists());\n committees[e3Id].threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n ICiphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getCommittee(\n uint256 e3Id\n ) external view returns (Committee memory) {\n return committees[e3Id];\n }\n}\n" - }, - "contracts/test/MockCiphernodeRegistry.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { ICiphernodeRegistry } from \"../interfaces/ICiphernodeRegistry.sol\";\n\ncontract MockCiphernodeRegistry is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(\n uint256 e3Id\n ) external pure returns (bytes memory) {\n if (e3Id == type(uint256).max) {\n return hex\"\";\n } else {\n return abi.encodePacked(keccak256(abi.encode(e3Id)));\n }\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n\ncontract MockCiphernodeRegistryEmptyKey is ICiphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n // solhint-disable no-empty-blocks\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256) external pure returns (bytes memory) {\n return hex\"\";\n }\n\n function isCiphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/MockComputeProvider.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport {\n IComputeProvider,\n IDecryptionVerifier\n} from \"../interfaces/IComputeProvider.sol\";\n\ncontract MockComputeProvider is IComputeProvider {\n error invalidParams();\n\n function validate(\n uint256,\n uint256,\n bytes memory params\n ) external pure returns (IDecryptionVerifier decryptionVerifier) {\n require(params.length == 32, invalidParams());\n // solhint-disable no-inline-assembly\n assembly {\n decryptionVerifier := mload(add(params, 32))\n }\n (decryptionVerifier) = abi.decode(params, (IDecryptionVerifier));\n }\n}\n" - }, - "contracts/test/MockDecryptionVerifier.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IDecryptionVerifier } from \"../interfaces/IDecryptionVerifier.sol\";\n\ncontract MockDecryptionVerifier is IDecryptionVerifier {\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IE3Program, IInputValidator } from \"../interfaces/IE3Program.sol\";\n\ncontract MockE3Program is IE3Program {\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\n\n function validate(\n uint256,\n uint256,\n bytes memory e3ProgramParams,\n bytes memory computeProviderParams\n )\n external\n pure\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator)\n {\n require(\n e3ProgramParams.length == 32 && computeProviderParams.length == 32,\n invalidParams(e3ProgramParams, computeProviderParams)\n );\n // solhint-disable no-inline-assembly\n assembly {\n inputValidator := mload(add(e3ProgramParams, 32))\n }\n encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001;\n }\n\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"../interfaces/IInputValidator.sol\";\n\ncontract MockInputValidator is IInputValidator {\n function validate(\n address,\n bytes memory params\n ) external pure returns (bytes memory input, bool success) {\n input = params;\n\n if (input.length == 3) {\n success = false;\n } else {\n success = true;\n }\n }\n}\n" - }, - "contracts/test/MockRegistryFilter.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ninterface IRegistry {\n function publishCommittee(\n uint256 e3Id,\n address[] calldata ciphernodes,\n bytes calldata publicKey\n ) external;\n}\n\ncontract MockNaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n Committee storage committee = committees[e3Id];\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\n committee.threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n IRegistry(registry).publishCommittee(e3Id, nodes, publicKey);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\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": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/deployments/sepolia/solcInputs/f32a0aa4ee06fa210859a817cc9dafc5.json b/packages/enclave-contracts/deployments/sepolia/solcInputs/f32a0aa4ee06fa210859a817cc9dafc5.json deleted file mode 100644 index 0d5c7deb2d..0000000000 --- a/packages/enclave-contracts/deployments/sepolia/solcInputs/f32a0aa4ee06fa210859a817cc9dafc5.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/interfaces/IE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IE3Program {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param e3Id ID of the E3.\n /// @param seed Seed for the computation.\n /// @param e3ProgramParams ABI encoded computation parameters.\n /// @param computeProviderParams ABI encoded compute provider parameters.\n /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n uint256 e3Id,\n uint256 seed,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n )\n external\n returns (bytes32 encryptionSchemeId, IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutputHash The keccak256 hash of output data to be verified.\n /// @param proof ABI encoded data to verify the ciphertextOutputHash.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes32 ciphertextOutputHash,\n bytes memory proof\n ) external returns (bool success);\n}\n" - }, - "contracts/interfaces/IInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the\n /// input of a computation.\n /// @param sender The account that is submitting the input.\n /// @param data The input to be verified.\n /// @return input The decoded, policy-approved application payload.\n function validate(\n address sender,\n bytes memory data\n ) external returns (bytes memory input);\n}\n" - }, - "contracts/test/MockE3Program.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IE3Program, IInputValidator } from \"../interfaces/IE3Program.sol\";\n\ncontract MockE3Program is IE3Program {\n error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);\n error InvalidInputValidator();\n error E3AlreadyInitialized();\n bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256(\"fhe.rs:BFV\");\n\n IInputValidator public inputValidator;\n mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes;\n\n constructor(IInputValidator _inputValidator) {\n if (address(_inputValidator) == address(0)) {\n revert InvalidInputValidator();\n }\n\n inputValidator = _inputValidator;\n }\n\n function validate(\n uint256 e3Id,\n uint256,\n bytes calldata e3ProgramParams,\n bytes calldata computeProviderParams\n ) external returns (bytes32, IInputValidator) {\n require(\n computeProviderParams.length == 32,\n invalidParams(e3ProgramParams, computeProviderParams)\n );\n\n require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized());\n paramsHashes[e3Id] = keccak256(e3ProgramParams);\n\n paramsHashes[e3Id] = keccak256(e3ProgramParams);\n return (ENCRYPTION_SCHEME_ID, inputValidator);\n }\n\n function verify(\n uint256,\n bytes32,\n bytes memory data\n ) external pure returns (bool success) {\n data;\n if (data.length > 0) success = true;\n }\n}\n" - }, - "contracts/test/MockInputValidator.sol": { - "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.27;\n\nimport { IInputValidator } from \"../interfaces/IInputValidator.sol\";\n\n/// @title MockInputValidator.\n/// @notice Enclave Input Validator\ncontract MockInputValidator is IInputValidator {\n error InvalidInput();\n\n /// @notice Validates input\n /// @param sender The account that is submitting the input.\n /// @param data The input to be verified.\n /// @return input The decoded, policy-approved application payload.\n function validate(\n address sender,\n bytes memory data\n ) external pure returns (bytes memory input) {\n if (data.length == 3 || sender == address(0)) {\n revert InvalidInput();\n }\n\n input = data;\n }\n}\n" - } - }, - "settings": { - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "optimizer": { - "enabled": true, - "runs": 800 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/enclave-contracts/hardhat.config.cts b/packages/enclave-contracts/hardhat.config.cts deleted file mode 100644 index 808466e6d0..0000000000 --- a/packages/enclave-contracts/hardhat.config.cts +++ /dev/null @@ -1,140 +0,0 @@ -import "./tasks/accounts"; -import "./tasks/ciphernode"; -import "./tasks/enclave"; -import "@nomicfoundation/hardhat-chai-matchers"; -import "@nomicfoundation/hardhat-toolbox"; -import dotenv from "dotenv"; -import "hardhat-deploy"; -import type { HardhatUserConfig } from "hardhat/config"; -import { vars } from "hardhat/config"; -import type { NetworkUserConfig } from "hardhat/types"; - -dotenv.config(); - -const { INFURA_KEY, MNEMONIC, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env; - -if (!INFURA_KEY || !ETHERSCAN_API_KEY) { - console.warn( - "Please set the INFURA_KEY, and ETHERSCAN_API_KEY environment variables to deploy and verify contracts", - ); -} - -if (!MNEMONIC && !PRIVATE_KEY) { - console.warn( - "Please set a mnemonic or private key to deploy contracts. If you set neither, hardhat will use a default mnemonic", - ); -} - -// Setting defaults so that tests will run -const mnemonic = - MNEMONIC || "test test test test test test test test test test test junk"; -const infuraApiKey = INFURA_KEY || "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"; - -const chainIds = { - "arbitrum-mainnet": 42161, - avalanche: 43114, - bsc: 56, - ganache: 1337, - hardhat: 31337, - mainnet: 1, - "optimism-mainnet": 10, - "polygon-mainnet": 137, - "polygon-mumbai": 80001, - sepolia: 11155111, -}; - -function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { - let jsonRpcUrl: string; - switch (chain) { - case "avalanche": - jsonRpcUrl = "https://api.avax.network/ext/bc/C/rpc"; - break; - case "bsc": - jsonRpcUrl = "https://bsc-dataseed1.binance.org"; - break; - default: - jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; - } - - let accounts: [string] | { mnemonic: string }; - if (PRIVATE_KEY) { - accounts = [PRIVATE_KEY]; - } else { - accounts = { mnemonic }; - } - - return { - accounts, - chainId: chainIds[chain], - url: jsonRpcUrl, - }; -} - -const config: HardhatUserConfig = { - defaultNetwork: "hardhat", - namedAccounts: { - deployer: 0, - }, - etherscan: { - apiKey: { - arbitrumOne: vars.get("ARBISCAN_API_KEY", ""), - avalanche: vars.get("SNOWTRACE_API_KEY", ""), - bsc: vars.get("BSCSCAN_API_KEY", ""), - mainnet: ETHERSCAN_API_KEY || "", - optimisticEthereum: vars.get("OPTIMISM_API_KEY", ""), - polygon: vars.get("POLYGONSCAN_API_KEY", ""), - polygonMumbai: vars.get("POLYGONSCAN_API_KEY", ""), - sepolia: ETHERSCAN_API_KEY || "", - }, - }, - gasReporter: { - currency: "USD", - enabled: process.env.REPORT_GAS ? true : false, - excludeContracts: [], - }, - networks: { - hardhat: { - accounts: { - mnemonic, - }, - chainId: chainIds.hardhat, - allowUnlimitedContractSize: true, - }, - arbitrum: getChainConfig("arbitrum-mainnet"), - avalanche: getChainConfig("avalanche"), - bsc: getChainConfig("bsc"), - mainnet: getChainConfig("mainnet"), - optimism: getChainConfig("optimism-mainnet"), - "polygon-mainnet": getChainConfig("polygon-mainnet"), - "polygon-mumbai": getChainConfig("polygon-mumbai"), - sepolia: getChainConfig("sepolia"), - }, - paths: { - artifacts: "./artifacts", - cache: "./cache", - sources: "./contracts", - tests: "./test", - }, - solidity: { - version: "0.8.27", - settings: { - metadata: { - // Not including the metadata hash - // https://github.com/paulrberg/hardhat-template/issues/31 - bytecodeHash: "none", - }, - // Disable the optimizer when debugging - // https://hardhat.org/hardhat-network/#solidity-optimizer-support - optimizer: { - enabled: true, - runs: 800, - }, - } - }, - typechain: { - outDir: "types", - target: "ethers-v6", - }, -}; - -export default config; diff --git a/packages/enclave-contracts/hardhat.config.ts b/packages/enclave-contracts/hardhat.config.ts new file mode 100644 index 0000000000..0aae4886ef --- /dev/null +++ b/packages/enclave-contracts/hardhat.config.ts @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import hardhatEthersChaiMatchers from "@nomicfoundation/hardhat-ethers-chai-matchers"; +import hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers"; +import hardhatNetworkHelpers from "@nomicfoundation/hardhat-network-helpers"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import hardhatTypechainPlugin from "@nomicfoundation/hardhat-typechain"; +import dotenv from "dotenv"; +import type { HardhatUserConfig } from "hardhat/config"; + +import { + ciphernodeAdd, + ciphernodeRemove, + ciphernodeSiblings, +} from "./tasks/ciphernode"; +import { + activateE3, + enableE3, + publishCiphertext, + publishCommittee, + publishInput, + publishPlaintext, + requestCommittee, +} from "./tasks/enclave"; +import { cleanDeploymentsTask } from "./tasks/utils"; + +dotenv.config(); + +const mnemonic = + process.env.MNEMONIC ?? + "test test test test test test test test test test test junk"; +const privateKey = process.env.PRIVATE_KEY!; +const infuraApiKey = process.env.INFURA_KEY!; + +const chainIds = { + "arbitrum-mainnet": 42161, + avalanche: 43114, + bsc: 56, + ganache: 1337, + hardhat: 31337, + mainnet: 1, + "optimism-mainnet": 10, + "polygon-mainnet": 137, + "polygon-mumbai": 80001, + sepolia: 11155111, + goerli: 5, +}; + +function getChainConfig(chain: keyof typeof chainIds, apiUrl: string) { + let jsonRpcUrl: string; + switch (chain) { + case "avalanche": + jsonRpcUrl = "https://api.avax.network/ext/bc/C/rpc"; + break; + case "bsc": + jsonRpcUrl = "https://bsc-dataseed1.binance.org"; + break; + default: + jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; + } + + let accounts: [string] | { count: number; mnemonic: string; path: string }; + if (privateKey) { + accounts = [privateKey]; + } else { + accounts = { + count: 10, + mnemonic: mnemonic, + path: "m/44'/60'/0'/0", + }; + } + + return { + accounts, + chainId: chainIds[chain], + url: jsonRpcUrl, + type: "http" as const, + chainType: "l1" as const, + blockExplorers: { + etherscan: { + apiUrl, + }, + }, + }; +} + +const config: HardhatUserConfig = { + plugins: [ + hardhatToolboxMochaEthersPlugin, + hardhatTypechainPlugin, + hardhatNetworkHelpers, + hardhatIgnitionEthers, + hardhatEthersChaiMatchers, + ], + tasks: [ + ciphernodeAdd, + ciphernodeRemove, + ciphernodeSiblings, + requestCommittee, + publishPlaintext, + publishCiphertext, + publishInput, + activateE3, + publishCommittee, + enableE3, + cleanDeploymentsTask, + ], + networks: { + hardhat: { + chainId: chainIds.hardhat, + type: "edr-simulated", + chainType: "l1", + }, + ganache: { + accounts: { + mnemonic, + }, + chainId: chainIds.ganache, + url: "http://localhost:8545", + type: "http", + }, + arbitrum: getChainConfig( + "arbitrum-mainnet", + process.env.ARBISCAN_API_KEY || "", + ), + avalanche: getChainConfig("avalanche", process.env.SNOWTRACE_API_KEY || ""), + bsc: getChainConfig("bsc", process.env.BSCSCAN_API_KEY || ""), + mainnet: getChainConfig("mainnet", process.env.ETHERSCAN_API_KEY || ""), + optimism: getChainConfig( + "optimism-mainnet", + process.env.OPTIMISM_API_KEY || "", + ), + "polygon-mainnet": getChainConfig( + "polygon-mainnet", + process.env.POLYGONSCAN_API_KEY || "", + ), + "polygon-mumbai": getChainConfig( + "polygon-mumbai", + process.env.POLYGONSCAN_API_KEY || "", + ), + sepolia: getChainConfig("sepolia", process.env.ETHERSCAN_API_KEY || ""), + goerli: getChainConfig("goerli", process.env.ETHERSCAN_API_KEY || ""), + }, + paths: { + artifacts: "./artifacts", + cache: "./cache", + sources: "./contracts", + tests: "./test", + }, + typechain: { + outDir: "./types", + tsNocheck: false, + }, + solidity: { + npmFilesToBuild: ["poseidon-solidity/PoseidonT3.sol"], + compilers: [ + { + version: "0.8.27", + settings: { + optimizer: { + enabled: true, + runs: 800, + }, + }, + }, + ], + }, +}; + +export default config; diff --git a/packages/enclave-contracts/ignition/modules/ciphernodeRegistry.ts b/packages/enclave-contracts/ignition/modules/ciphernodeRegistry.ts new file mode 100644 index 0000000000..e374e8f928 --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/ciphernodeRegistry.ts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("CiphernodeRegistry", (m) => { + const enclaveAddress = m.getParameter("enclaveAddress"); + const owner = m.getParameter("owner"); + + const poseidonT3 = m.library("PoseidonT3"); + + const cipherNodeRegistry = m.contract( + "CiphernodeRegistryOwnable", + [owner, enclaveAddress], + { + libraries: { + PoseidonT3: poseidonT3, + }, + }, + ); + + return { cipherNodeRegistry }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/enclave.ts b/packages/enclave-contracts/ignition/modules/enclave.ts new file mode 100644 index 0000000000..eec6c0da2f --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/enclave.ts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("Enclave", (m) => { + const params = m.getParameter("params"); + const owner = m.getParameter("owner"); + const maxDuration = m.getParameter("maxDuration"); + const registry = m.getParameter("registry"); + + const poseidonT3 = m.library("PoseidonT3"); + + const enclave = m.contract( + "Enclave", + [owner, registry, maxDuration, [params]], + { + libraries: { + PoseidonT3: poseidonT3, + }, + }, + ); + + return { enclave }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistry.ts b/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistry.ts new file mode 100644 index 0000000000..c4705df409 --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistry.ts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockCiphernodeRegistry", (m) => { + const mockCiphernodeRegistry = m.contract("MockCiphernodeRegistry"); + + return { mockCiphernodeRegistry }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistryEmptyKey.ts b/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistryEmptyKey.ts new file mode 100644 index 0000000000..d6e5aa64eb --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockCiphernodeRegistryEmptyKey.ts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockCiphernodeRegistryEmptyKey", (m) => { + const mockCiphernodeRegistryEmptyKey = m.contract( + "MockCiphernodeRegistryEmptyKey", + ); + + return { mockCiphernodeRegistryEmptyKey }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockComputeProvider.ts b/packages/enclave-contracts/ignition/modules/mockComputeProvider.ts new file mode 100644 index 0000000000..3a1ae2fe15 --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockComputeProvider.ts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockComputeProvider", (m) => { + const mockComputeProvider = m.contract("MockComputeProvider"); + + return { mockComputeProvider }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockDecryptionVerifier.ts b/packages/enclave-contracts/ignition/modules/mockDecryptionVerifier.ts new file mode 100644 index 0000000000..d2f06b0f5a --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockDecryptionVerifier.ts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockDecryptionVerifier", (m) => { + const mockDecryptionVerifier = m.contract("MockDecryptionVerifier"); + + return { mockDecryptionVerifier }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockE3Program.ts b/packages/enclave-contracts/ignition/modules/mockE3Program.ts new file mode 100644 index 0000000000..c0734e6c5a --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockE3Program.ts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockE3Program", (m) => { + const mockInputValidator = m.getParameter("mockInputValidator"); + + const mockE3Program = m.contract("MockE3Program", [mockInputValidator]); + + return { mockE3Program }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockInputValidator.ts b/packages/enclave-contracts/ignition/modules/mockInputValidator.ts new file mode 100644 index 0000000000..21f33ffd8c --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/mockInputValidator.ts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("MockInputValidator", (m) => { + const mockInputValidator = m.contract("MockInputValidator"); + + return { mockInputValidator }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/naiveRegistryFilter.ts b/packages/enclave-contracts/ignition/modules/naiveRegistryFilter.ts new file mode 100644 index 0000000000..c1a9a8913c --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/naiveRegistryFilter.ts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("NaiveRegistryFilter", (m) => { + const ciphernodeRegistryAddress = m.getParameter("ciphernodeRegistryAddress"); + const owner = m.getParameter("owner"); + + const naiveRegistryFilter = m.contract("NaiveRegistryFilter", [ + owner, + ciphernodeRegistryAddress, + ]); + + return { naiveRegistryFilter }; +}) as any; diff --git a/packages/enclave-contracts/ignition/modules/poseidonT3.ts b/packages/enclave-contracts/ignition/modules/poseidonT3.ts new file mode 100644 index 0000000000..14f2b3efb5 --- /dev/null +++ b/packages/enclave-contracts/ignition/modules/poseidonT3.ts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +export default buildModule("PoseidonT3", (m) => { + const poseidon = m.library("PoseidonT3"); + + return { poseidon }; +}) as any; diff --git a/packages/enclave-contracts/package.json b/packages/enclave-contracts/package.json index c9cf4000f6..273207cf42 100644 --- a/packages/enclave-contracts/package.json +++ b/packages/enclave-contracts/package.json @@ -3,6 +3,7 @@ "description": "Enclave is an open-source protocol for Encrypted Execution Environments (E3).", "version": "0.0.10-test", "license": "LGPL-3.0-only", + "type": "module", "author": { "name": "gnosisguild", "url": "https://github.com/gnosisguild" @@ -10,69 +11,113 @@ "exports": { "./deploy/enclave": { "import": { - "types": "./dist/deploy/enclave.d.mts", - "default": "./dist/deploy/enclave.mjs" + "types": "./dist/scripts/deployEnclave.d.ts", + "default": "./dist/scripts/deployEnclave.js" }, "require": { - "types": "./dist/deploy/enclave.d.ts", - "default": "./dist/deploy/enclave.js" + "types": "./dist/scripts/deployEnclave.d.ts", + "default": "./dist/scripts/deployEnclave.js" } }, "./deploy/mocks": { "import": { - "types": "./dist/deploy/mocks.d.mts", - "default": "./dist/deploy/mocks.mjs" + "types": "./dist/scripts/deployMocks.d.ts", + "default": "./dist/scripts/deployMocks.js" }, "require": { - "types": "./dist/deploy/mocks.d.ts", - "default": "./dist/deploy/mocks.js" + "types": "./dist/scripts/deployMocks.d.ts", + "default": "./dist/scripts/deployMocks.js" } }, + "./tasks/ciphernode": { + "import": { + "types": "./dist/tasks/ciphernode.d.ts", + "default": "./dist/tasks/ciphernode.js" + }, + "require": { + "types": "./dist/tasks/ciphernode.d.ts", + "default": "./dist/tasks/ciphernode.js" + } + }, + "./tasks/enclave": { + "import": { + "types": "./dist/tasks/enclave.d.ts", + "default": "./dist/tasks/enclave.js" + }, + "require": { + "types": "./dist/tasks/enclave.d.ts", + "default": "./dist/tasks/enclave.js" + } + }, + "./tasks/utils": { + "import": { + "types": "./dist/tasks/utils.d.ts", + "default": "./dist/tasks/utils.js" + }, + "require": { + "types": "./dist/tasks/utils.d.ts", + "default": "./dist/tasks/utils.js" + } + }, + "./scripts/*": "./scripts/*", "./contracts/*": "./contracts/*", "./artifacts/*": "./artifacts/*", "./types": { "import": { - "types": "./dist/types/index.d.mts", - "default": "./dist/types/index.mjs" + "types": "./dist/types/index.d.ts", + "default": "./dist/types/index.js" }, "require": { "types": "./dist/types/index.d.ts", "default": "./dist/types/index.js" } + }, + "./ignition/modules/*": { + "import": { + "types": "./dist/ignition/modules/*.d.ts", + "default": "./dist/ignition/modules/*.js" + }, + "require": { + "types": "./dist/ignition/modules/*.d.ts", + "default": "./dist/ignition/modules/*.js" + } } }, "devDependencies": { "@enclave-e3/config": "workspace:*", - "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", - "@nomicfoundation/hardhat-ethers": "^3.0.5", - "@nomicfoundation/hardhat-network-helpers": "^1.0.10", - "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.2", + "@nomicfoundation/hardhat-ethers": "4", + "@nomicfoundation/hardhat-ethers-chai-matchers": "^3.0.0", + "@nomicfoundation/hardhat-ignition": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^3.0.1", + "@nomicfoundation/hardhat-network-helpers": "3", + "@nomicfoundation/hardhat-toolbox-mocha-ethers": "3.0.0", + "@nomicfoundation/hardhat-typechain": "3", + "@nomicfoundation/hardhat-verify": "3", "@openzeppelin/contracts": "^5.0.2", "@openzeppelin/contracts-upgradeable": "^5.0.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", - "@types/chai": "^4.3.11", + "@types/chai": "^4.3.20", + "@types/chai-as-promised": "^8.0.2", "@types/fs-extra": "^11.0.4", - "@types/mocha": "^10.0.6", - "@types/node": "^22.7.5", + "@types/mocha": "^10.0.10", + "@types/node": "^22.18.0", "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.11.0", "@zk-kit/lean-imt": "^2.1.0", "@zk-kit/lean-imt.sol": "2.0.0", - "chai": "^4.3.10", + "chai": "^5.3.3", "cross-env": "^7.0.3", "dotenv": "^16.4.5", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "ethers": "^6.9.0", + "ethers": "^6.15.0", + "forge-std": "github:foundry-rs/forge-std#v1.9.4", "fs-extra": "^11.2.0", - "hardhat": "^2.22.0", - "hardhat-deploy": "^0.12.1", + "hardhat": "^3.0.1", "hardhat-gas-reporter": "^2.2.0", "lodash": "^4.17.21", - "mocha": "^10.2.0", + "mocha": "^11.7.1", "poseidon-lite": "^0.3.0", "poseidon-solidity": "^0.0.5", "prettier": "^3.1.1", @@ -106,27 +151,31 @@ "access": "public" }, "scripts": { - "clean": "rimraf ./artifacts ./cache ./coverage ./types ./dist ./coverage.json && pnpm typechain", + "clean": "rimraf ./artifacts ./cache ./coverage ./types ./dist ./coverage.json", + "clean:ignition:deployments": "rimraf ./ignition/deployments/chain-31337", + "clean:deployments": "hardhat utils:clean-deployments && pnpm clean:ignition:deployments", "build": "pnpm compile", "compile": "pnpm compile:contracts && pnpm compile:ts", "compile:contracts": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile", - "compile:ts": "pnpm typechain && tsup", - "coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && pnpm typechain", - "deploy": "hardhat deploy --tags enclave", - "deploy:mocks": "hardhat deploy --tags enclave,mocks", + "compile:ts": "tsc", + "coverage": "pnpm test --coverage", + "deploy": "hardhat run scripts/run.ts", + "deploy:mocks": "export DEPLOY_MOCKS=true && pnpm clean:deployments && pnpm run deploy", + "e3:activate": "hardhat e3:activate", + "e3:enable": "hardhat e3:enable", "ciphernode:add": "hardhat ciphernode:add", "ciphernode:remove": "hardhat ciphernode:remove", + "ciphernode:siblings": "hardhat ciphernode:siblings", "committee:new": "hardhat committee:new", "lint": "pnpm lint:sol && pnpm lint:ts && pnpm prettier:check", - "lint:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\"", + "lint:sol": "solhint --max-warnings 10 \"contracts/**/*.sol\"", "lint:ts": "eslint --ignore-path ./.eslintignore --ext .js,.ts .", - "postcompile": "pnpm typechain", "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"", "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"", - "task:deployLock": "hardhat task:deployLock", - "task:withdraw": "hardhat task:withdraw", - "test": "hardhat test", - "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain", + "test": "hardhat test mocha", + "test:registryFilter": "pnpm run test test/CiphernodeRegistry/NaiveRegistryFilter.spec.ts", + "test:enclave": "pnpm run test test/Enclave.spec.ts", + "test:ciphernodeRegistry": "pnpm run test test/CiphernodeRegistry/CiphernodeRegistryOwnable.spec.ts", "prerelease": "pnpm clean && pnpm compile && pnpm typechain", "release": "pnpm publish" }, diff --git a/packages/enclave-contracts/scripts/deployAndSave/ciphernodeRegistryOwnable.ts b/packages/enclave-contracts/scripts/deployAndSave/ciphernodeRegistryOwnable.ts new file mode 100644 index 0000000000..7154c3638e --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/ciphernodeRegistryOwnable.ts @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import CiphernodeRegistryModule from "../../ignition/modules/ciphernodeRegistry"; +import { + CiphernodeRegistryOwnable, + CiphernodeRegistryOwnable__factory as CiphernodeRegistryOwnableFactory, +} from "../../types"; +import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; + +/** + * The arguments for the deployAndSaveCiphernodeRegistryOwnable function + */ +export interface CiphernodeRegistryOwnableArgs { + enclaveAddress?: string; + owner?: string; + hre: HardhatRuntimeEnvironment; +} + +/** + * Deploys the CiphernodeRegistryOwnable contract and saves the deployment arguments + * @param param0 - The deployment arguments + * @returns The deployed CiphernodeRegistryOwnable contract + */ +export const deployAndSaveCiphernodeRegistryOwnable = async ({ + enclaveAddress, + owner, + hre, +}: CiphernodeRegistryOwnableArgs): Promise<{ + ciphernodeRegistry: CiphernodeRegistryOwnable; +}> => { + const { ignition, ethers } = await hre.network.connect(); + const [signer] = await ethers.getSigners(); + const chain = (await signer.provider?.getNetwork())?.name ?? "localhost"; + + const preDeployedArgs = readDeploymentArgs("CiphernodeRegistry", chain); + + if ( + !enclaveAddress || + !owner || + (preDeployedArgs?.constructorArgs?.enclaveAddress === enclaveAddress && + preDeployedArgs?.constructorArgs?.owner === owner) + ) { + if (!preDeployedArgs?.address) { + throw new Error( + "CiphernodeRegistry address not found, it must be deployed first", + ); + } + const ciphernodeRegistryContract = CiphernodeRegistryOwnableFactory.connect( + preDeployedArgs.address, + signer, + ); + return { ciphernodeRegistry: ciphernodeRegistryContract }; + } + + const ciphernodeRegistry = await ignition.deploy(CiphernodeRegistryModule, { + parameters: { + CiphernodeRegistry: { + enclaveAddress, + owner, + }, + }, + }); + + await ciphernodeRegistry.cipherNodeRegistry.waitForDeployment(); + + const blockNumber = await ethers.provider.getBlockNumber(); + + const ciphernodeRegistryAddress = + await ciphernodeRegistry.cipherNodeRegistry.getAddress(); + + storeDeploymentArgs( + { + constructorArgs: { enclaveAddress: enclaveAddress, owner }, + blockNumber, + address: ciphernodeRegistryAddress, + }, + "CiphernodeRegistry", + chain, + ); + + const ciphernodeRegistryContract = CiphernodeRegistryOwnableFactory.connect( + ciphernodeRegistryAddress, + ); + + return { ciphernodeRegistry: ciphernodeRegistryContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/enclave.ts b/packages/enclave-contracts/scripts/deployAndSave/enclave.ts new file mode 100644 index 0000000000..dd0c5440b2 --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/enclave.ts @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import EnclaveModule from "../../ignition/modules/enclave"; +import { Enclave, Enclave__factory as EnclaveFactory } from "../../types"; +import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; + +/** + * The arguments for the deployAndSaveEnclave function + */ +export interface EnclaveArgs { + params?: string; + owner?: string; + maxDuration?: string; + registry?: string; + hre: HardhatRuntimeEnvironment; +} + +/** + * Deploys the Enclave contract and saves the deployment arguments + * @param param0 - The deployment arguments + * @returns The deployed Enclave contract + */ +export const deployAndSaveEnclave = async ({ + params, + owner, + maxDuration, + registry, + hre, +}: EnclaveArgs): Promise<{ enclave: Enclave }> => { + const { ignition, ethers } = await hre.network.connect(); + + const [signer] = await ethers.getSigners(); + + const chain = hre.globalOptions.network; + const preDeployedArgs = readDeploymentArgs("Enclave", chain); + + if ( + !params || + !owner || + !maxDuration || + !registry || + (preDeployedArgs?.constructorArgs?.params === params && + preDeployedArgs?.constructorArgs?.owner === owner && + preDeployedArgs?.constructorArgs?.maxDuration === maxDuration && + preDeployedArgs?.constructorArgs?.registry === registry) + ) { + if (!preDeployedArgs?.address) { + throw new Error("Enclave address not found, it must be deployed first"); + } + const enclaveContract = EnclaveFactory.connect( + preDeployedArgs.address, + signer, + ); + return { enclave: enclaveContract }; + } + + const enclave = await ignition.deploy(EnclaveModule, { + parameters: { + Enclave: { + params, + owner, + maxDuration, + registry, + }, + }, + }); + + await enclave.enclave.waitForDeployment(); + + const enclaveAddress = await enclave.enclave.getAddress(); + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + constructorArgs: { params, owner, maxDuration, registry }, + blockNumber, + address: enclaveAddress, + }, + "Enclave", + chain, + ); + + const enclaveContract = EnclaveFactory.connect(enclaveAddress, signer); + + return { enclave: enclaveContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockComputeProvider.ts b/packages/enclave-contracts/scripts/deployAndSave/mockComputeProvider.ts new file mode 100644 index 0000000000..435610584f --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/mockComputeProvider.ts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import MockComputeProviderModule from "../../ignition/modules/mockComputeProvider"; +import { + MockComputeProvider, + MockComputeProvider__factory as MockComputeProviderFactory, +} from "../../types"; +import { storeDeploymentArgs } from "../utils"; + +export const deployAndSaveMockComputeProvider = async ( + hre: HardhatRuntimeEnvironment, +): Promise<{ + computeProvider: MockComputeProvider; +}> => { + const { ignition, ethers } = await hre.network.connect(); + + const computeProvider = await ignition.deploy(MockComputeProviderModule); + + await computeProvider.mockComputeProvider.waitForDeployment(); + + const computeProviderAddress = + await computeProvider.mockComputeProvider.getAddress(); + + const [signer] = await ethers.getSigners(); + const chain = hre.globalOptions.network; + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + blockNumber, + address: computeProviderAddress, + }, + "MockComputeProvider", + chain, + ); + + const computeProviderContract = MockComputeProviderFactory.connect( + computeProviderAddress, + signer, + ); + + return { computeProvider: computeProviderContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockDecryptionVerifier.ts b/packages/enclave-contracts/scripts/deployAndSave/mockDecryptionVerifier.ts new file mode 100644 index 0000000000..0a2bdfe294 --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/mockDecryptionVerifier.ts @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import MockDecryptionVerifierModule from "../../ignition/modules/mockDecryptionVerifier"; +import { + MockDecryptionVerifier, + MockDecryptionVerifier__factory as MockDecryptionVerifierFactory, +} from "../../types"; +import { storeDeploymentArgs } from "../utils"; + +export const deployAndSaveMockDecryptionVerifier = async ( + hre: HardhatRuntimeEnvironment, +): Promise<{ + decryptionVerifier: MockDecryptionVerifier; +}> => { + const { ignition, ethers } = await hre.network.connect(); + const [signer] = await ethers.getSigners(); + const chain = hre.globalOptions.network; + + const decryptionVerifier = await ignition.deploy( + MockDecryptionVerifierModule, + ); + + await decryptionVerifier.mockDecryptionVerifier.waitForDeployment(); + const decryptionVerifierAddress = + await decryptionVerifier.mockDecryptionVerifier.getAddress(); + + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + blockNumber, + address: decryptionVerifierAddress, + }, + "MockDecryptionVerifier", + chain, + ); + + const decryptionVerifierContract = MockDecryptionVerifierFactory.connect( + decryptionVerifierAddress, + signer, + ); + + return { decryptionVerifier: decryptionVerifierContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts b/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts new file mode 100644 index 0000000000..da1778b4b1 --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import MockInputValidatorModule from "../../ignition/modules/mockInputValidator"; +import { + MockInputValidator, + MockInputValidator__factory as MockInputValidatorFactory, +} from "../../types"; +import { storeDeploymentArgs } from "../utils"; + +export const deployAndSaveMockInputValidator = async ( + hre: HardhatRuntimeEnvironment, +): Promise<{ + inputValidator: MockInputValidator; +}> => { + const { ignition, ethers } = await hre.network.connect(); + const [signer] = await ethers.getSigners(); + const inputValidator = await ignition.deploy(MockInputValidatorModule); + await inputValidator.mockInputValidator.waitForDeployment(); + const inputValidatorAddress = + await inputValidator.mockInputValidator.getAddress(); + + const chain = hre.globalOptions.network; + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + blockNumber, + address: inputValidatorAddress, + }, + "MockInputValidator", + chain, + ); + + const inputValidatorContract = MockInputValidatorFactory.connect( + inputValidatorAddress, + signer, + ); + + return { inputValidator: inputValidatorContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts b/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts new file mode 100644 index 0000000000..e7dda5f7bf --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import MockE3ProgramModule from "../../ignition/modules/mockE3Program"; +import { + MockE3Program, + MockE3Program__factory as MockE3ProgramFactory, +} from "../../types"; +import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; + +interface MockProgramArgs { + mockInputValidator: string; + hre: HardhatRuntimeEnvironment; +} + +export const deployAndSaveMockProgram = async ({ + mockInputValidator, + hre, +}: MockProgramArgs): Promise<{ + e3Program: MockE3Program; +}> => { + const { ignition, ethers } = await hre.network.connect(); + const [signer] = await ethers.getSigners(); + const chain = (await signer.provider?.getNetwork())?.name ?? "localhost"; + + const preDeployedArgs = readDeploymentArgs("MockE3Program", chain); + + if ( + preDeployedArgs?.constructorArgs?.mockInputValidator === mockInputValidator + ) { + const e3ProgramContract = MockE3ProgramFactory.connect( + preDeployedArgs.address, + signer, + ); + return { e3Program: e3ProgramContract }; + } + + const e3Program = await ignition.deploy(MockE3ProgramModule, { + parameters: { + MockE3Program: { + mockInputValidator, + }, + }, + }); + + await e3Program.mockE3Program.waitForDeployment(); + + const e3ProgramAddress = await e3Program.mockE3Program.getAddress(); + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + constructorArgs: { mockInputValidator }, + blockNumber, + address: e3ProgramAddress, + }, + "MockE3Program", + chain, + ); + + const mockProgramContract = MockE3ProgramFactory.connect( + e3ProgramAddress, + signer, + ); + + return { e3Program: mockProgramContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/naiveRegistryFilter.ts b/packages/enclave-contracts/scripts/deployAndSave/naiveRegistryFilter.ts new file mode 100644 index 0000000000..913d7310b3 --- /dev/null +++ b/packages/enclave-contracts/scripts/deployAndSave/naiveRegistryFilter.ts @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; + +import NaiveRegistryFilterModule from "../../ignition/modules/naiveRegistryFilter"; +import { + NaiveRegistryFilter, + NaiveRegistryFilter__factory as NaiveRegistryFilterFactory, +} from "../../types"; +import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; + +export interface NaiveRegistryFilterArgs { + ciphernodeRegistryAddress?: string; + owner?: string; + hre: HardhatRuntimeEnvironment; +} + +export const deployAndSaveNaiveRegistryFilter = async ({ + ciphernodeRegistryAddress, + owner, + hre, +}: NaiveRegistryFilterArgs): Promise<{ + naiveRegistryFilter: NaiveRegistryFilter; +}> => { + const { ignition, ethers } = await hre.network.connect(); + const [signer] = await ethers.getSigners(); + const chain = hre.globalOptions.network; + + const preDeployedArgs = readDeploymentArgs("NaiveRegistryFilter", chain); + if ( + !ciphernodeRegistryAddress || + !owner || + (preDeployedArgs?.constructorArgs?.ciphernodeRegistryAddress === + ciphernodeRegistryAddress && + preDeployedArgs?.constructorArgs?.owner === owner) + ) { + if (!preDeployedArgs?.address) { + throw new Error( + "NaiveRegistryFilter address not found, it must be deployed first", + ); + } + const naiveRegistryFilterContract = NaiveRegistryFilterFactory.connect( + preDeployedArgs.address, + signer, + ); + return { naiveRegistryFilter: naiveRegistryFilterContract }; + } + + const naiveRegistryFilter = await ignition.deploy(NaiveRegistryFilterModule, { + parameters: { + NaiveRegistryFilter: { + ciphernodeRegistryAddress, + owner, + }, + }, + }); + + await naiveRegistryFilter.naiveRegistryFilter.waitForDeployment(); + + const naiveRegistryFilterAddress = + await naiveRegistryFilter.naiveRegistryFilter.getAddress(); + + const blockNumber = await ethers.provider.getBlockNumber(); + + storeDeploymentArgs( + { + constructorArgs: { + ciphernodeRegistryAddress: ciphernodeRegistryAddress, + owner, + }, + blockNumber, + address: naiveRegistryFilterAddress, + }, + "NaiveRegistryFilter", + chain, + ); + + const naiveRegistryFilterContract = NaiveRegistryFilterFactory.connect( + naiveRegistryFilterAddress, + signer, + ); + + return { naiveRegistryFilter: naiveRegistryFilterContract }; +}; diff --git a/packages/enclave-contracts/scripts/deployEnclave.ts b/packages/enclave-contracts/scripts/deployEnclave.ts new file mode 100644 index 0000000000..de9d52c166 --- /dev/null +++ b/packages/enclave-contracts/scripts/deployEnclave.ts @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import hre from "hardhat"; + +import { deployAndSaveCiphernodeRegistryOwnable } from "./deployAndSave/ciphernodeRegistryOwnable"; +import { deployAndSaveEnclave } from "./deployAndSave/enclave"; +import { deployAndSaveNaiveRegistryFilter } from "./deployAndSave/naiveRegistryFilter"; +import { deployMocks } from "./deployMocks"; + +/** + * Deploys the Enclave contracts + */ +export const deployEnclave = async (withMocks?: boolean) => { + const { ethers } = await hre.network.connect(); + + const [owner] = await ethers.getSigners(); + + const ownerAddress = await owner.getAddress(); + + const polynomial_degree = ethers.toBigInt(2048); + const plaintext_modulus = ethers.toBigInt(1032193); + const moduli = [ethers.toBigInt("18014398492704769")]; + + const encoded = ethers.AbiCoder.defaultAbiCoder().encode( + ["uint256", "uint256", "uint256[]"], + [polynomial_degree, plaintext_modulus, moduli], + ); + + const THIRTY_DAYS_IN_SECONDS = 60 * 60 * 24 * 30; + const addressOne = "0x0000000000000000000000000000000000000001"; + + const { enclave } = await deployAndSaveEnclave({ + params: encoded, + owner: ownerAddress, + maxDuration: THIRTY_DAYS_IN_SECONDS.toString(), + registry: addressOne, + hre, + }); + + const enclaveAddress = await enclave.getAddress(); + + console.log("Enclave deployed to: ", enclaveAddress); + + const { ciphernodeRegistry } = await deployAndSaveCiphernodeRegistryOwnable({ + enclaveAddress: enclaveAddress, + owner: ownerAddress, + hre, + }); + + const ciphernodeRegistryAddress = await ciphernodeRegistry.getAddress(); + + console.log("CiphernodeRegistry deployed to: ", ciphernodeRegistryAddress); + + const { naiveRegistryFilter } = await deployAndSaveNaiveRegistryFilter({ + ciphernodeRegistryAddress: ciphernodeRegistryAddress, + owner: ownerAddress, + hre, + }); + + const naiveRegistryFilterAddress = await naiveRegistryFilter.getAddress(); + + console.log("NaiveRegistryFilter deployed to: ", naiveRegistryFilterAddress); + + const registryAddress = await enclave.ciphernodeRegistry(); + + if (registryAddress === ciphernodeRegistryAddress) { + console.log(`Enclave contract already has registry`); + } else { + const tx = await enclave.setCiphernodeRegistry(ciphernodeRegistryAddress); + await tx.wait(); + + console.log(`Enclave contract updated with registry`); + } + + // Deploy mocks only if specified + const shouldDeployMocks = process.env.DEPLOY_MOCKS === "true" || withMocks; + + if (shouldDeployMocks) { + const { decryptionVerifierAddress, e3ProgramAddress } = await deployMocks(); + + const encryptionSchemeId = ethers.keccak256( + ethers.toUtf8Bytes("fhe.rs:BFV"), + ); + + console.log("encryptionSchemeId", encryptionSchemeId); + + const deployedDecryptionVerifier = + await enclave.decryptionVerifiers(encryptionSchemeId); + if (deployedDecryptionVerifier === decryptionVerifierAddress) { + console.log(`DecryptionVerifier already set in Enclave contract`); + } else { + const tx = await enclave.setDecryptionVerifier( + encryptionSchemeId, + decryptionVerifierAddress, + ); + await tx.wait(); + console.log( + `Successfully set MockDecryptionVerifier in Enclave contract`, + ); + } + + const tx = await enclave.enableE3Program(e3ProgramAddress); + await tx.wait(); + console.log(`Successfully enabled E3 Program in Enclave contract`); + } +}; diff --git a/packages/enclave-contracts/scripts/deployMocks.ts b/packages/enclave-contracts/scripts/deployMocks.ts new file mode 100644 index 0000000000..72f33d5adc --- /dev/null +++ b/packages/enclave-contracts/scripts/deployMocks.ts @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import hre from "hardhat"; + +import { deployAndSaveMockComputeProvider } from "./deployAndSave/mockComputeProvider"; +import { deployAndSaveMockDecryptionVerifier } from "./deployAndSave/mockDecryptionVerifier"; +import { deployAndSaveMockInputValidator } from "./deployAndSave/mockInputValidator"; +import { deployAndSaveMockProgram } from "./deployAndSave/mockProgram"; + +export interface MockDeployments { + computeProviderAddress: string; + decryptionVerifierAddress: string; + inputValidatorAddress: string; + e3ProgramAddress: string; +} + +/** + * Deploys the mock contracts and returns the addresses. + * @param enclaveAddress - The address of the enclave contract. + * @returns The addresses of the mock contracts. + */ +export const deployMocks = async (): Promise => { + const { computeProvider } = await deployAndSaveMockComputeProvider(hre); + + const computeProviderAddress = await computeProvider.getAddress(); + + const { decryptionVerifier } = await deployAndSaveMockDecryptionVerifier(hre); + + const decryptionVerifierAddress = await decryptionVerifier.getAddress(); + + const { inputValidator } = await deployAndSaveMockInputValidator(hre); + + const inputValidatorAddress = await inputValidator.getAddress(); + + const { e3Program } = await deployAndSaveMockProgram({ + mockInputValidator: inputValidatorAddress, + hre, + }); + + const e3ProgramAddress = await e3Program.getAddress(); + + console.log(` + MockDeployments: + ---------------------------------------------------------------------- + MockComputeProvider:${computeProviderAddress} + MockDecryptionVerifier:${decryptionVerifierAddress} + MockInputValidator:${inputValidatorAddress} + MockE3Program:${e3ProgramAddress} + `); + + return { + computeProviderAddress, + decryptionVerifierAddress, + inputValidatorAddress, + e3ProgramAddress, + }; +}; diff --git a/packages/enclave-contracts/scripts/run.ts b/packages/enclave-contracts/scripts/run.ts new file mode 100644 index 0000000000..c7248c4475 --- /dev/null +++ b/packages/enclave-contracts/scripts/run.ts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import { deployEnclave } from "./deployEnclave"; + +deployEnclave().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/enclave-contracts/scripts/utils.ts b/packages/enclave-contracts/scripts/utils.ts new file mode 100644 index 0000000000..86418dc172 --- /dev/null +++ b/packages/enclave-contracts/scripts/utils.ts @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import fs from "fs"; +import path from "path"; + +const deploymentsFile = path.join("deployed_contracts.json"); + +// Type for deployment arguments +export interface DeploymentArgs { + address: string; + constructorArgs?: Record; + blockNumber?: number | null; +} + +// Type for chain-specific deployments +export interface ChainDeployments { + [contractName: string]: DeploymentArgs; +} + +// Type for the deployments object organized by chain +export interface Deployments { + [chainName: string]: ChainDeployments; +} + +/** + * Store the deployment arguments for a given contract and chain + * @param args - The deployment arguments to store + * @param contractName - The name of the contract to store the deployments for + * @param chain - The chain to store the deployments for + */ +export const storeDeploymentArgs = ( + args: DeploymentArgs, + contractName: string, + chain: string, +): void => { + let deployments: Deployments = {}; + + // Read existing deployments if file exists + if (fs.existsSync(deploymentsFile)) { + try { + deployments = JSON.parse( + fs.readFileSync(deploymentsFile, "utf8"), + ) as Deployments; + } catch (error) { + console.warn("Failed to parse existing deployments file, starting fresh"); + deployments = {}; + } + } else { + // create a new file + deployments = {}; + fs.writeFileSync(deploymentsFile, JSON.stringify(deployments, null, 2)); + } + + // Initialize chain if it doesn't exist + if (!deployments[chain]) { + deployments[chain] = {}; + } + + // Add or update the contract deployment for the specific chain + deployments[chain][contractName] = args; + + fs.writeFileSync(deploymentsFile, JSON.stringify(deployments, null, 2)); +}; + +/** + * Read the deployment arguments for a given contract and chain + * @param contractName - The name of the contract to read the deployments from + * @param chain - The chain to read the deployments from + * @returns The deployment arguments for the given contract and chain + */ +export const readDeploymentArgs = ( + contractName: string, + chain: string, +): DeploymentArgs | undefined => { + if (!fs.existsSync(deploymentsFile)) { + // create a new file + fs.writeFileSync(deploymentsFile, JSON.stringify({}, null, 2)); + return undefined; + } + + const deployments = JSON.parse( + fs.readFileSync(deploymentsFile, "utf8"), + ) as Deployments; + return deployments[chain]?.[contractName]; +}; + +/** + * Read all the deployments from the deployments file + * @returns All the deployments from the deployments file + */ +export const readAllDeployments = (): Deployments => { + if (!fs.existsSync(deploymentsFile)) { + return {}; + } + + try { + return JSON.parse(fs.readFileSync(deploymentsFile, "utf8")) as Deployments; + } catch (error) { + console.warn("Failed to parse deployments file"); + return {}; + } +}; + +/** + * Clean the deployments for a given network + * @param network + */ +export const cleanDeployments = (network: string): void => { + if (!fs.existsSync(deploymentsFile)) { + return; + } + + const deployments = readAllDeployments(); + if (deployments[network]) { + delete deployments[network]; + } + fs.writeFileSync(deploymentsFile, JSON.stringify(deployments, null, 2)); +}; diff --git a/packages/enclave-contracts/tasks/accounts.ts b/packages/enclave-contracts/tasks/accounts.ts deleted file mode 100644 index c82f3e61d1..0000000000 --- a/packages/enclave-contracts/tasks/accounts.ts +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { task } from "hardhat/config"; - -task("accounts", "Prints the list of accounts", async (_taskArgs, hre) => { - const accounts = await hre.ethers.getSigners(); - - for (const account of accounts) { - console.log(account.address); - } -}); diff --git a/packages/enclave-contracts/tasks/ciphernode.ts b/packages/enclave-contracts/tasks/ciphernode.ts index 6a7475fdbd..fede694761 100644 --- a/packages/enclave-contracts/tasks/ciphernode.ts +++ b/packages/enclave-contracts/tasks/ciphernode.ts @@ -4,70 +4,99 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. import { LeanIMT } from "@zk-kit/lean-imt"; +import { ZeroAddress } from "ethers"; import { task } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; import { poseidon2 } from "poseidon-lite"; -task("ciphernode:add", "Register a ciphernode to the registry") - .addParam("ciphernodeAddress", "address of ciphernode to register") - .setAction(async function (taskArguments: TaskArguments, hre) { - const registry = await hre.deployments.get("CiphernodeRegistryOwnable"); +export const ciphernodeAdd = task( + "ciphernode:add", + "Register a ciphernode to the registry", +) + .addOption({ + name: "ciphernodeAddress", + description: "address of ciphernode to register", + defaultValue: ZeroAddress, + }) + .setAction(async () => ({ + default: async ({ ciphernodeAddress }, hre) => { + const { deployAndSaveCiphernodeRegistryOwnable } = await import( + "../scripts/deployAndSave/ciphernodeRegistryOwnable" + ); + const { ciphernodeRegistry } = + await deployAndSaveCiphernodeRegistryOwnable({ hre }); - const registryContract = await hre.ethers.getContractAt( - "CiphernodeRegistryOwnable", - registry.address, - ); + const tx = await ciphernodeRegistry.addCiphernode(ciphernodeAddress); + await tx.wait(); + console.log(`Ciphernode ${ciphernodeAddress} registered`); + }, + })) + .build(); - const tx = await registryContract.addCiphernode( - taskArguments.ciphernodeAddress, - ); - await tx.wait(); +export const ciphernodeRemove = task( + "ciphernode:remove", + "Remove a ciphernode from the registry", +) + .addOption({ + name: "ciphernodeAddress", + description: "address of ciphernode to remove", + defaultValue: ZeroAddress, + }) + .addOption({ + name: "siblings", + description: "comma separated siblings from tree proof", + defaultValue: "", + }) + .setAction(async () => ({ + default: async ({ ciphernodeAddress, siblings }, hre) => { + const { deployAndSaveCiphernodeRegistryOwnable } = await import( + "../scripts/deployAndSave/ciphernodeRegistryOwnable" + ); + const { ciphernodeRegistry } = + await deployAndSaveCiphernodeRegistryOwnable({ hre }); - console.log(`Ciphernode ${taskArguments.ciphernodeAddress} registered`); - }); + const siblingsArray = siblings.split(",").map((s: string) => BigInt(s)); -task("ciphernode:remove", "Remove a ciphernode from the registry") - .addParam("ciphernodeAddress", "address of ciphernode to remove") - .addParam("siblings", "comma separated siblings from tree proof") - .setAction(async function (taskArguments: TaskArguments, hre) { - const registry = await hre.deployments.get("CiphernodeRegistryOwnable"); + const tx = await ciphernodeRegistry.removeCiphernode( + ciphernodeAddress, + siblingsArray, + ); + await tx.wait(); - const registryContract = await hre.ethers.getContractAt( - "CiphernodeRegistryOwnable", - registry.address, - ); + console.log(`Ciphernode ${ciphernodeAddress} removed`); + }, + })) + .build(); - const siblings = taskArguments.siblings - .split(",") - .map((s: string) => BigInt(s)); +export const ciphernodeSiblings = task( + "ciphernode:siblings", + "Get the sibling of a ciphernode in the registry", +) + .addOption({ + name: "ciphernodeAddress", + description: "address of ciphernode to get siblings for", + defaultValue: ZeroAddress, + }) + .addOption({ + name: "ciphernodeAddresses", + description: + "comma separated addresses of ciphernodes in the order they were added to the registry", + defaultValue: ZeroAddress, + }) + .setAction(async () => ({ + default: async ({ ciphernodeAddress, ciphernodeAddresses }, _) => { + const hash = (a: bigint, b: bigint) => poseidon2([a, b]); + const tree = new LeanIMT(hash); - const tx = await registryContract.removeCiphernode( - taskArguments.ciphernodeAddress, - siblings, - ); - await tx.wait(); + const addresses = ciphernodeAddresses.split(","); - console.log(`Ciphernode ${taskArguments.ciphernodeAddress} removed`); - }); + for (const address of addresses) { + tree.insert(BigInt(address)); + } -task("ciphernode:siblings", "Get the sibling of a ciphernode in the registry") - .addParam("ciphernodeAddress", "address of ciphernode to get siblings for") - .addParam( - "ciphernodeAddresses", - "comma separated addresses of ciphernodes in the order they were added to the registry", - ) - .setAction(async function (taskArguments: TaskArguments) { - const hash = (a: bigint, b: bigint) => poseidon2([a, b]); - const tree = new LeanIMT(hash); + const index = tree.indexOf(BigInt(ciphernodeAddress)); + const { siblings } = tree.generateProof(index); - const addresses = taskArguments.ciphernodeAddresses.split(","); - - for (const address of addresses) { - tree.insert(BigInt(address)); - } - - const index = tree.indexOf(BigInt(taskArguments.ciphernodeAddress)); - const { siblings } = tree.generateProof(index); - - console.log(`Siblings for ${taskArguments.ciphernodeAddress}: ${siblings}`); - }); + console.log(`Siblings for ${ciphernodeAddress}: ${siblings}`); + }, + })) + .build(); diff --git a/packages/enclave-contracts/tasks/enclave.ts b/packages/enclave-contracts/tasks/enclave.ts index 7323cc80e8..960c396125 100644 --- a/packages/enclave-contracts/tasks/enclave.ts +++ b/packages/enclave-contracts/tasks/enclave.ts @@ -3,343 +3,479 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +import { ZeroAddress, zeroPadValue } from "ethers"; import fs from "fs"; -import { task, types } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; +import { task } from "hardhat/config"; +import { ArgumentType } from "hardhat/types/arguments"; -task( +import { readDeploymentArgs } from "../scripts/utils"; + +export const requestCommittee = task( "committee:new", "Request a new ciphernode committee, will use E3 mock contracts by default", ) - .addOptionalParam( - "filter", - "address of filter contract to use", - undefined, - types.string, - ) - .addOptionalParam( - "thresholdQuorum", - "threshold quorum for committee", - 2, - types.int, - ) - .addOptionalParam( - "thresholdTotal", - "threshold total for committee", - 2, - types.int, - ) - .addOptionalParam( - "windowStart", - "timestamp start of window for the E3 (default: now)", - Math.floor(Date.now() / 1000), - types.int, - ) - .addOptionalParam( - "windowEnd", - "timestamp end of window for the E3 (default: now + 1 day)", - Math.floor(Date.now() / 1000) + 86400, - types.int, - ) - .addOptionalParam( - "duration", - "duration in seconds of the E3 (default: 1 day)", - 86400, - types.int, - ) - .addOptionalParam( - "e3Address", - "address of the E3 program", - undefined, - types.string, - ) - .addOptionalParam( - "e3Params", - "parameters for the E3 program", - undefined, - types.string, - ) - .addOptionalParam( - "computeParams", - "parameters for the compute provider", - undefined, - types.string, - ) - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - let e3Address = taskArguments.e3Address; - if (!e3Address) { - const mockE3Program = await hre.deployments.get("MockE3Program"); - if (!mockE3Program) { - throw new Error("MockE3Program not deployed"); + .addOption({ + name: "filter", + description: "address of filter contract to use", + defaultValue: ZeroAddress, + type: ArgumentType.STRING, + }) + .addOption({ + name: "thresholdQuorum", + description: "threshold quorum for committee", + defaultValue: 2, + type: ArgumentType.INT, + }) + .addOption({ + name: "thresholdTotal", + description: "threshold total for committee", + defaultValue: 2, + type: ArgumentType.INT, + }) + .addOption({ + name: "windowStart", + description: "timestamp start of window for the E3 (default: now)", + defaultValue: Math.floor(Date.now() / 1000), + type: ArgumentType.INT, + }) + .addOption({ + name: "windowEnd", + description: "timestamp end of window for the E3 (default: now + 1 day)", + defaultValue: Math.floor(Date.now() / 1000) + 86400, + type: ArgumentType.INT, + }) + .addOption({ + name: "duration", + description: "duration in seconds of the E3 (default: 1 day)", + defaultValue: 86400, + type: ArgumentType.INT, + }) + .addOption({ + name: "e3Address", + description: "address of the E3 program", + defaultValue: ZeroAddress, + type: ArgumentType.STRING, + }) + .addOption({ + name: "e3Params", + description: "parameters for the E3 program", + defaultValue: ZeroAddress, + type: ArgumentType.STRING, + }) + .addOption({ + name: "computeParams", + description: "parameters for the compute provider", + defaultValue: ZeroAddress, + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ( + { + filter, + thresholdQuorum, + thresholdTotal, + windowStart, + windowEnd, + duration, + e3Address, + e3Params, + computeParams, + }, + hre, + ) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" + ); + + const { enclave } = await deployAndSaveEnclave({ hre }); + + const enclaveArgs = readDeploymentArgs( + "Enclave", + hre.globalOptions.network, + ); + + if (!enclaveArgs) { + throw new Error("Enclave deployment arguments not found"); + } + + const registryArgs = readDeploymentArgs( + "CiphernodeRegistry", + hre.globalOptions.network, + ); + + if (!registryArgs) { + throw new Error("CiphernodeRegistry deployment arguments not found"); } - e3Address = mockE3Program.address; - } - let filterAddress = taskArguments.filter; - if (!filterAddress) { - const naiveRegistryFilter = await hre.deployments.get( + const filterArgs = readDeploymentArgs( "NaiveRegistryFilter", + hre.globalOptions.network, ); - if (!naiveRegistryFilter) { - throw new Error("NaiveRegistryFilter not deployed"); + + if (!filterArgs) { + throw new Error("NaiveRegistryFilter deployment arguments not found"); } - filterAddress = naiveRegistryFilter.address; - } - let e3Params = taskArguments.e3Params; - if (!e3Params) { - const MockInputValidatorChecker = await hre.deployments.get( - "MockInputValidatorChecker", + const mockE3ProgramArgs = readDeploymentArgs( + "MockE3Program", + hre.globalOptions.network, ); - if (!MockInputValidatorChecker) { - throw new Error("MockInputValidatorChecker not deployed"); + + let e3ProgramParams = e3Params; + + const mockInputValidatorArgs = readDeploymentArgs( + "MockInputValidator", + hre.globalOptions.network, + ); + if (e3ProgramParams === ZeroAddress) { + if (!mockInputValidatorArgs) { + throw new Error("MockInputValidator deployment arguments not found"); + } + e3ProgramParams = zeroPadValue(mockInputValidatorArgs.address, 32); } - e3Params = hre.ethers.zeroPadValue(MockInputValidatorChecker.address, 32); - } - let computeParams = taskArguments.computeParams; - if (!computeParams) { - // no compute params provided, use mock - const MockDecryptionVerifier = await hre.deployments.get( + let computeProviderParams = computeParams; + const mockDecryptionVerifierArgs = readDeploymentArgs( "MockDecryptionVerifier", + hre.globalOptions.network, ); - if (!MockDecryptionVerifier) { - throw new Error("MockDecryptionVerifier not deployed"); + if (computeProviderParams === ZeroAddress) { + if (!mockDecryptionVerifierArgs) { + throw new Error( + "MockDecryptionVerifier deployment arguments not found", + ); + } + computeProviderParams = zeroPadValue( + mockDecryptionVerifierArgs.address, + 32, + ); } - computeParams = hre.ethers.zeroPadValue( - MockDecryptionVerifier.address, - 32, + + console.log({ + filter: filter === ZeroAddress ? filterArgs.address : filter, + threshold: [thresholdQuorum, thresholdTotal], + startWindow: [windowStart, windowEnd], + duration: duration, + e3Program: + e3Address === ZeroAddress ? mockE3ProgramArgs!.address : e3Address, + e3ProgramParams, + computeProviderParams, + }); + const tx = await enclave.request( + { + filter: filter === ZeroAddress ? filterArgs.address : filter, + threshold: [thresholdQuorum, thresholdTotal], + startWindow: [windowStart, windowEnd], + duration: duration, + e3Program: + e3Address === ZeroAddress ? mockE3ProgramArgs!.address : e3Address, + e3ProgramParams, + computeProviderParams, + }, + { value: "1000000000000000000" }, + ); + + console.log("Requesting committee... ", tx.hash); + await tx.wait(); + + console.log(`Committee requested`); + }, + })) + .build(); + +export const enableE3 = task("enclave:enableE3", "Enable an E3 program") + .addOption({ + name: "e3Address", + description: "address of the E3 program", + defaultValue: ZeroAddress, + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Address }, hre) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" ); - } - try { - const enableE3Tx = await enclaveContract.enableE3Program(e3Address); - await enableE3Tx.wait(); - } catch (e) { - console.log("E3 program enabling failed, probably already enabled: ", e); - } + const { enclave } = await deployAndSaveEnclave({ hre }); - const tx = await enclaveContract.request( - { - filter: filterAddress, - threshold: [ - taskArguments.thresholdQuorum, - taskArguments.thresholdTotal, - ], - startWindow: [taskArguments.windowStart, taskArguments.windowEnd], - duration: taskArguments.duration, - e3Program: e3Address, - e3ProgramParams: e3Params, - computeProviderParams: computeParams, - }, - // 1 ETH - { value: "1000000000000000000" }, - ); - - console.log("Requesting committee... ", tx.hash); - await tx.wait(); - - console.log(`Committee requested`); - }); - -task("enclave:enableE3", "Enable an E3 program") - .addParam("e3Address", "address of the E3 program") - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - const tx = await enclaveContract.enableE3Program(taskArguments.e3Address); - - console.log("Enabling E3 program... ", tx.hash); - await tx.wait(); - - console.log(`E3 program enabled`); - }); - -task("committee:publish", "Publish the publickey of the committee") - .addOptionalParam( - "filter", - "address of filter contract to use (defaults to NaiveRegistryFilter)", - ) - .addParam("e3Id", "Id of the E3 program", undefined, types.int) - .addParam( - "nodes", - "list of node address in the committee, comma separated", - undefined, - types.string, - ) - .addParam("publicKey", "public key of the committee", undefined, types.string) - .setAction(async function (taskArguments: TaskArguments, hre) { - let filterAddress = taskArguments.filter; - if (!taskArguments.filter) { - filterAddress = (await hre.deployments.get("NaiveRegistryFilter")) - .address; - - if (!filterAddress) { - throw new Error("NaiveRegistryFilter not deployed"); + const tx = await enclave.enableE3Program(e3Address); + + console.log("Enabling E3 program... ", tx.hash); + await tx.wait(); + + console.log(`E3 program enabled`); + }, + })) + .build(); + +export const publishCommittee = task( + "committee:publish", + "Publish the publickey of the committee", +) + .addOption({ + name: "e3Id", + description: "Id of the E3 program", + defaultValue: 0, + type: ArgumentType.INT, + }) + .addOption({ + name: "nodes", + description: "list of node address in the committee, comma separated", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "publicKey", + description: "public key of the committee", + defaultValue: "", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Id, nodes, publicKey }, hre) => { + const { deployAndSaveNaiveRegistryFilter } = await import( + "../scripts/deployAndSave/naiveRegistryFilter" + ); + + const { naiveRegistryFilter } = await deployAndSaveNaiveRegistryFilter({ + hre, + }); + + const nodesToSend = nodes + .split(",") + .map((node) => node.trim()) + .filter((node) => node.length > 0); + + if (nodesToSend.length === 0 && nodes.length > 0) { + throw new Error("Invalid nodes format: no valid addresses found"); } - } - const filterContract = await hre.ethers.getContractAt( - "NaiveRegistryFilter", - filterAddress, - ); + const tx = await naiveRegistryFilter.publishCommittee( + e3Id, + nodesToSend, + publicKey, + ); + + console.log("Publishing committee... ", tx.hash); + await tx.wait(); + console.log(`Committee public key published`); + }, + })) + .build(); + +export const activateE3 = task("e3:activate", "Activate an E3 program") + .addOption({ + name: "e3Id", + description: "Id of the E3 program", + defaultValue: 0, + type: ArgumentType.INT, + }) + .addOption({ + name: "publicKey", + description: "public key of the committee", + defaultValue: "", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Id, publicKey }, hre) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" + ); - const nodes = taskArguments.nodes.split(","); + const { enclave } = await deployAndSaveEnclave({ hre }); - if (!Array.isArray(nodes)) { - throw new Error( - "Could not parse nodes: Nodes must be input as comma separated list", + const tx = await enclave.activate(e3Id, publicKey); + + console.log("Activating E3 program... ", tx.hash); + await tx.wait(); + + console.log(`E3 program activated`); + }, + })) + .build(); + +export const publishInput = task( + "e3:publishInput", + "Publish input for an E3 program", +) + .addOption({ + name: "e3Id", + description: "Id of the E3 program", + defaultValue: 0, + type: ArgumentType.INT, + }) + .addOption({ + name: "data", + description: "data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "dataFile", + description: "file containing data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Id, data, dataFile }, hre) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" ); - } - - const tx = await filterContract.publishCommittee( - taskArguments.e3Id, - nodes, - taskArguments.publicKey, - ); - - console.log("Publishing committee... ", tx.hash); - await tx.wait(); - console.log(`Committee public key published`); - }); - -task("e3:activate", "Activate an E3 program") - .addParam("e3Id", "Id of the E3 program") - .addParam("publicKey", "public key of the committee") - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - const tx = await enclaveContract.activate( - taskArguments.e3Id, - taskArguments.publicKey, - ); - - console.log("Activating E3 program... ", tx.hash); - await tx.wait(); - - console.log(`E3 program activated`); - }); - -task("e3:publishInput", "Publish input for an E3 program") - .addParam("e3Id", "Id of the E3 program") - .addOptionalParam("data", "data to publish") - .addOptionalParam("dataFile", "file containing data to publish") - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - let data = taskArguments.data; - - if (taskArguments.dataFile) { - const file = fs.readFileSync(taskArguments.dataFile); - data = file.toString(); - } - - const tx = await enclaveContract.publishInput(taskArguments.e3Id, data); - - console.log("Publishing input... ", tx.hash); - await tx.wait(); - - console.log(`Input published`); - }); - -task("e3:publishCiphertext", "Publish ciphertext output for an E3 program") - .addParam("e3Id", "Id of the E3 program") - .addOptionalParam("data", "data to publish") - .addOptionalParam("dataFile", "file containing data to publish") - .addOptionalParam("proof", "proof to publish") - .addOptionalParam("proofFile", "file containing proof to publish") - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - let data = taskArguments.data; - - if (taskArguments.dataFile) { - const file = fs.readFileSync(taskArguments.dataFile); - data = "0x" + file.toString("hex"); - } - - let proof = taskArguments.proof; - - if (taskArguments.proofFile) { - const file = fs.readFileSync(taskArguments.proofFile); - proof = file.toString(); - } - - const tx = await enclaveContract.publishCiphertextOutput( - taskArguments.e3Id, - data, - proof, - ); - - console.log("Publishing ciphertext... ", tx.hash); - await tx.wait(); - - console.log(`Ciphertext published`); - }); - -task("e3:publishPlaintext", "Publish plaintext output for an E3 program") - .addParam("e3Id", "Id of the E3 program") - .addOptionalParam("data", "data to publish") - .addOptionalParam("dataFile", "file containing data to publish") - .addOptionalParam("proof", "proof to publish") - .addOptionalParam("proofFile", "file containing proof to publish") - .setAction(async function (taskArguments: TaskArguments, hre) { - const enclave = await hre.deployments.get("Enclave"); - - const enclaveContract = await hre.ethers.getContractAt( - "Enclave", - enclave.address, - ); - - let data = taskArguments.data; - - if (taskArguments.dataFile) { - const file = fs.readFileSync(taskArguments.dataFile); - data = file.toString(); - } - - let proof = taskArguments.proof; - - if (taskArguments.proofFile) { - const file = fs.readFileSync(taskArguments.proofFile); - proof = file.toString(); - } - - const tx = await enclaveContract.publishPlaintextOutput( - taskArguments.e3Id, - data, - proof, - ); - - console.log("Publishing ciphertext... ", tx.hash); - await tx.wait(); - - console.log(`Ciphertext published`); - }); + + const { enclave } = await deployAndSaveEnclave({ hre }); + + let dataToSend = data; + + if (dataFile) { + const file = fs.readFileSync(dataFile); + dataToSend = file.toString(); + } + + const tx = await enclave.publishInput(e3Id, dataToSend); + + console.log("Publishing input... ", tx.hash); + await tx.wait(); + + console.log(`Input published`); + }, + })) + .build(); + +export const publishCiphertext = task( + "e3:publishCiphertext", + "Publish ciphertext output for an E3 program", +) + .addOption({ + name: "e3Id", + description: "Id of the E3 program", + defaultValue: 0, + type: ArgumentType.INT, + }) + .addOption({ + name: "data", + description: "data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "dataFile", + description: "file containing data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "proof", + description: "proof to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "proofFile", + description: "file containing proof to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Id, data, dataFile, proof, proofFile }, hre) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" + ); + + const { enclave } = await deployAndSaveEnclave({ hre }); + + let dataToSend = data; + + if (dataFile) { + const file = fs.readFileSync(dataFile); + dataToSend = "0x" + file.toString("hex"); + } + + let proofToSend = proof; + + if (proofFile) { + const file = fs.readFileSync(proofFile); + proofToSend = file.toString(); + } + + const tx = await enclave.publishCiphertextOutput( + e3Id, + dataToSend, + proofToSend, + ); + + console.log("Publishing ciphertext... ", tx.hash); + await tx.wait(); + + console.log(`Ciphertext published`); + }, + })) + .build(); + +export const publishPlaintext = task( + "e3:publishPlaintext", + "Publish plaintext output for an E3 program", +) + .addOption({ + name: "e3Id", + description: "Id of the E3 program", + defaultValue: 0, + type: ArgumentType.INT, + }) + .addOption({ + name: "data", + description: "data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "dataFile", + description: "file containing data to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "proof", + description: "proof to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .addOption({ + name: "proofFile", + description: "file containing proof to publish", + defaultValue: "", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: async ({ e3Id, data, dataFile, proof, proofFile }, hre) => { + const { deployAndSaveEnclave } = await import( + "../scripts/deployAndSave/enclave" + ); + + const { enclave } = await deployAndSaveEnclave({ hre }); + + let dataToSend = data; + + if (dataFile) { + const file = fs.readFileSync(dataFile); + dataToSend = file.toString(); + } + + let proofToSend = proof; + + if (proofFile) { + const file = fs.readFileSync(proofFile); + proofToSend = file.toString(); + } + + const tx = await enclave.publishPlaintextOutput( + e3Id, + dataToSend, + proofToSend, + ); + + console.log("Publishing plaintext... ", tx.hash); + await tx.wait(); + + console.log(`Plaintext published`); + }, + })) + .build(); diff --git a/packages/enclave-contracts/tasks/utils.ts b/packages/enclave-contracts/tasks/utils.ts new file mode 100644 index 0000000000..040cda2cf2 --- /dev/null +++ b/packages/enclave-contracts/tasks/utils.ts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +import { task } from "hardhat/config"; +import { ArgumentType } from "hardhat/types/arguments"; + +import { cleanDeployments } from "../scripts/utils"; + +export const cleanDeploymentsTask = task( + "utils:clean-deployments", + "Clean deployments for a given network", +) + .addOption({ + name: "chain", + description: "network to clean deployments for", + defaultValue: "localhost", + type: ArgumentType.STRING, + }) + .setAction(async () => ({ + default: ({ chain }) => { + cleanDeployments(chain); + }, + })) + .build(); diff --git a/packages/enclave-contracts/test/CiphernodeRegistry/CiphernodeRegistryOwnable.spec.ts b/packages/enclave-contracts/test/CiphernodeRegistry/CiphernodeRegistryOwnable.spec.ts index a960fcdf6a..0f6548e4f3 100644 --- a/packages/enclave-contracts/test/CiphernodeRegistry/CiphernodeRegistryOwnable.spec.ts +++ b/packages/enclave-contracts/test/CiphernodeRegistry/CiphernodeRegistryOwnable.spec.ts @@ -3,20 +3,25 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { LeanIMT } from "@zk-kit/lean-imt"; import { expect } from "chai"; -import { ethers } from "hardhat"; +import { network } from "hardhat"; import { poseidon2 } from "poseidon-lite"; -import { deployCiphernodeRegistryOwnableFixture } from "../fixtures/CiphernodeRegistryOwnable.fixture"; -import { naiveRegistryFilterFixture } from "../fixtures/NaiveRegistryFilter.fixture"; -import { PoseidonT3Fixture } from "../fixtures/PoseidonT3.fixture"; +import CiphernodeRegistryModule from "../../ignition/modules/ciphernodeRegistry"; +import NaiveRegistryFilterModule from "../../ignition/modules/naiveRegistryFilter"; +import { + CiphernodeRegistryOwnable__factory as CiphernodeRegistryFactory, + NaiveRegistryFilter__factory as NaiveRegistryFilterFactory, +} from "../../types"; const AddressOne = "0x0000000000000000000000000000000000000001"; const AddressTwo = "0x0000000000000000000000000000000000000002"; const AddressThree = "0x0000000000000000000000000000000000000003"; +const { ethers, networkHelpers, ignition } = await network.connect(); +const { loadFixture } = networkHelpers; + const data = "0xda7a"; const dataHash = ethers.keccak256(data); @@ -26,18 +31,33 @@ const hash = (a: bigint, b: bigint) => poseidon2([a, b]); describe("CiphernodeRegistryOwnable", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); - if (!owner) throw new Error("getSigners() did not return expected output"); - if (!notTheOwner) - throw new Error("getSigners() did not return expected output"); - const poseidon = await PoseidonT3Fixture(); - const registry = await deployCiphernodeRegistryOwnableFixture( - owner.address, - owner.address, - await poseidon.getAddress(), + + const registryContract = await ignition.deploy(CiphernodeRegistryModule, { + parameters: { + CiphernodeRegistry: { + enclaveAddress: await owner.getAddress(), + owner: await owner.getAddress(), + }, + }, + }); + + const filterContract = await ignition.deploy(NaiveRegistryFilterModule, { + parameters: { + NaiveRegistryFilter: { + owner: await owner.getAddress(), + ciphernodeRegistryAddress: + await registryContract.cipherNodeRegistry.getAddress(), + }, + }, + }); + + const registry = CiphernodeRegistryFactory.connect( + await registryContract.cipherNodeRegistry.getAddress(), + owner, ); - const filter = await naiveRegistryFilterFixture( - owner.address, - await registry.getAddress(), + const filter = NaiveRegistryFilterFactory.connect( + await filterContract.naiveRegistryFilter.getAddress(), + owner, ); const tree = new LeanIMT(hash); @@ -143,7 +163,7 @@ describe("CiphernodeRegistryOwnable", function () { it("reverts if filter.requestCommittee() fails", async function () { const { owner, registry, filter, request } = await loadFixture(setup); - await filter.setRegistry(owner.address); + await filter.setRegistry(await owner.getAddress()); await filter.requestCommittee(request.e3Id, request.threshold); await filter.setRegistry(await registry.getAddress()); @@ -219,7 +239,7 @@ describe("CiphernodeRegistryOwnable", function () { const { registry, notTheOwner } = await loadFixture(setup); await expect(registry.connect(notTheOwner).addCiphernode(AddressThree)) .to.be.revertedWithCustomError(registry, "OwnableUnauthorizedAccount") - .withArgs(notTheOwner.address); + .withArgs(await notTheOwner.getAddress()); }); it("adds the ciphernode to the registry", async function () { const { registry } = await loadFixture(setup); @@ -256,7 +276,7 @@ describe("CiphernodeRegistryOwnable", function () { registry.connect(notTheOwner).removeCiphernode(AddressOne, []), ) .to.be.revertedWithCustomError(registry, "OwnableUnauthorizedAccount") - .withArgs(notTheOwner.address); + .withArgs(await notTheOwner.getAddress()); }); it("removes the ciphernode from the registry", async function () { const { registry } = await loadFixture(setup); diff --git a/packages/enclave-contracts/test/CiphernodeRegistry/NaiveRegistryFilter.spec.ts b/packages/enclave-contracts/test/CiphernodeRegistry/NaiveRegistryFilter.spec.ts index a7014943e5..af32a57bea 100644 --- a/packages/enclave-contracts/test/CiphernodeRegistry/NaiveRegistryFilter.spec.ts +++ b/packages/enclave-contracts/test/CiphernodeRegistry/NaiveRegistryFilter.spec.ts @@ -3,37 +3,58 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { LeanIMT } from "@zk-kit/lean-imt"; import { expect } from "chai"; -import { ethers } from "hardhat"; +import { network } from "hardhat"; import { poseidon2 } from "poseidon-lite"; -import { deployCiphernodeRegistryOwnableFixture } from "../fixtures/CiphernodeRegistryOwnable.fixture"; -import { naiveRegistryFilterFixture } from "../fixtures/NaiveRegistryFilter.fixture"; -import { PoseidonT3Fixture } from "../fixtures/PoseidonT3.fixture"; +import CiphernodeRegistryModule from "../../ignition/modules/ciphernodeRegistry"; +import NaiveRegistryFilterModule from "../../ignition/modules/naiveRegistryFilter"; +import { + CiphernodeRegistryOwnable__factory as CiphernodeRegistryFactory, + NaiveRegistryFilter__factory as NaiveRegistryFilterFactory, +} from "../../types"; const AddressOne = "0x0000000000000000000000000000000000000001"; const AddressTwo = "0x0000000000000000000000000000000000000002"; const AddressThree = "0x0000000000000000000000000000000000000003"; +const { ethers, networkHelpers, ignition } = await network.connect(); +const { loadFixture } = networkHelpers; + // Hash function used to compute the tree nodes. const hash = (a: bigint, b: bigint) => poseidon2([a, b]); describe("NaiveRegistryFilter", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); - if (!owner) throw new Error("Bad getSigners output"); - if (!notTheOwner) throw new Error("Bad getSigners output"); - const poseidon = await PoseidonT3Fixture(); - const registry = await deployCiphernodeRegistryOwnableFixture( - owner.address, - owner.address, - await poseidon.getAddress(), + + const registryContract = await ignition.deploy(CiphernodeRegistryModule, { + parameters: { + CiphernodeRegistry: { + enclaveAddress: await owner.getAddress(), + owner: await owner.getAddress(), + }, + }, + }); + + const filterContract = await ignition.deploy(NaiveRegistryFilterModule, { + parameters: { + NaiveRegistryFilter: { + owner: await owner.getAddress(), + ciphernodeRegistryAddress: + await registryContract.cipherNodeRegistry.getAddress(), + }, + }, + }); + + const registry = CiphernodeRegistryFactory.connect( + await registryContract.cipherNodeRegistry.getAddress(), + owner, ); - const filter = await naiveRegistryFilterFixture( - owner.address, - await registry.getAddress(), + const filter = NaiveRegistryFilterFactory.connect( + await filterContract.naiveRegistryFilter.getAddress(), + owner, ); const tree = new LeanIMT(hash); @@ -59,7 +80,7 @@ describe("NaiveRegistryFilter", function () { describe("constructor / initialize()", function () { it("should set the owner", async function () { const { owner, filter } = await loadFixture(setup); - expect(await filter.owner()).to.equal(owner.address); + expect(await filter.owner()).to.equal(await owner.getAddress()); }); it("should set the registry", async function () { const { registry, filter } = await loadFixture(setup); @@ -69,16 +90,14 @@ describe("NaiveRegistryFilter", function () { describe("requestCommittee()", function () { it("should revert if the caller is not the registry", async function () { - const { notTheOwner, filter, request } = await loadFixture(setup); + const { filter, request } = await loadFixture(setup); await expect( - filter - .connect(notTheOwner) - .requestCommittee(request.e3Id, request.threshold), + filter.requestCommittee(request.e3Id, request.threshold), ).to.be.revertedWithCustomError(filter, "OnlyRegistry"); }); it("should revert if a committee has already been requested for the given e3Id", async function () { const { filter, request, owner } = await loadFixture(setup); - await filter.setRegistry(owner.address); + await filter.setRegistry(await owner.getAddress()); await filter.requestCommittee(request.e3Id, request.threshold); await expect( filter.requestCommittee(request.e3Id, request.threshold), @@ -86,14 +105,14 @@ describe("NaiveRegistryFilter", function () { }); it("should set the threshold for the requested committee", async function () { const { filter, owner, request } = await loadFixture(setup); - await filter.setRegistry(owner.address); + await filter.setRegistry(await owner.getAddress()); await filter.requestCommittee(request.e3Id, request.threshold); const committee = await filter.getCommittee(request.e3Id); expect(committee.threshold).to.deep.equal(request.threshold); }); it("should return true when a committee is requested", async function () { const { filter, owner, request } = await loadFixture(setup); - await filter.setRegistry(owner.address); + await filter.setRegistry(await owner.getAddress()); const result = await filter.requestCommittee.staticCall( request.e3Id, request.threshold, @@ -210,14 +229,16 @@ describe("NaiveRegistryFilter", function () { describe("setRegistry()", function () { it("should revert if the caller is not the owner", async function () { const { filter, notTheOwner } = await loadFixture(setup); - await expect(filter.connect(notTheOwner).setRegistry(notTheOwner.address)) + await expect( + filter.connect(notTheOwner).setRegistry(await notTheOwner.getAddress()), + ) .to.be.revertedWithCustomError(filter, "OwnableUnauthorizedAccount") - .withArgs(notTheOwner.address); + .withArgs(await notTheOwner.getAddress()); }); it("should set the registry", async function () { const { filter, owner } = await loadFixture(setup); - await filter.setRegistry(owner.address); - expect(await filter.registry()).to.equal(owner.address); + await filter.setRegistry(await owner.getAddress()); + expect(await filter.registry()).to.equal(await owner.getAddress()); }); }); diff --git a/packages/enclave-contracts/test/Enclave.spec.ts b/packages/enclave-contracts/test/Enclave.spec.ts index 80ff994491..878966410b 100644 --- a/packages/enclave-contracts/test/Enclave.spec.ts +++ b/packages/enclave-contracts/test/Enclave.spec.ts @@ -3,125 +3,179 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import "@nomicfoundation/hardhat-chai-matchers"; -import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; -import { - loadFixture, - mine, - time, -} from "@nomicfoundation/hardhat-network-helpers"; import { LeanIMT } from "@zk-kit/lean-imt"; import { expect } from "chai"; -import { ZeroHash } from "ethers"; -import { ethers } from "hardhat"; +import { network } from "hardhat"; import { poseidon2 } from "poseidon-lite"; -import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; -import { deployCiphernodeRegistryFixture } from "./fixtures/MockCiphernodeRegistry.fixture"; -import { deployComputeProviderFixture } from "./fixtures/MockComputeProvider.fixture"; -import { deployDecryptionVerifierFixture } from "./fixtures/MockDecryptionVerifier.fixture"; -import { deployE3ProgramFixture } from "./fixtures/MockE3Program.fixture"; -import { deployInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; -import { PoseidonT3Fixture } from "./fixtures/PoseidonT3.fixture"; - -const abiCoder = ethers.AbiCoder.defaultAbiCoder(); -const AddressTwo = "0x0000000000000000000000000000000000000002"; -const AddressSix = "0x0000000000000000000000000000000000000006"; -const encryptionSchemeId = - "0x2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c6"; -const newEncryptionSchemeId = - "0x0000000000000000000000000000000000000000000000000000000000000002"; - -const FilterFail = AddressTwo; -const FilterOkay = AddressSix; - -const data = "0xda7a"; -const dataHash = ethers.keccak256(data); -const _publicKeyHash = ethers.keccak256(abiCoder.encode(["uint256"], [0])); -const proof = "0x1337"; -const polynomial_degree = ethers.toBigInt(2048); -const plaintext_modulus = ethers.toBigInt(1032193); -const moduli = [ethers.toBigInt("18014398492704769")]; // 0x3FFFFFFF000001 - -const encodedE3ProgramParams = ethers.AbiCoder.defaultAbiCoder().encode( - ["uint256", "uint256", "uint256[]"], - [polynomial_degree, plaintext_modulus, moduli], -); - -// Hash function used to compute the tree nodes. -const hash = (a: bigint, b: bigint) => poseidon2([a, b]); +import EnclaveModule from "../ignition/modules/enclave"; +import MockCiphernodeRegistryModule from "../ignition/modules/mockCiphernodeRegistry"; +import MockCiphernodeRegistryEmptyKeyModule from "../ignition/modules/mockCiphernodeRegistryEmptyKey"; +import mockComputeProviderModule from "../ignition/modules/mockComputeProvider"; +import MockDecryptionVerifierModule from "../ignition/modules/mockDecryptionVerifier"; +import MockE3ProgramModule from "../ignition/modules/mockE3Program"; +import MockInputValidatorModule from "../ignition/modules/mockInputValidator"; +import NaiveRegistryFilterModule from "../ignition/modules/naiveRegistryFilter"; +import { + CiphernodeRegistryOwnable__factory as CiphernodeRegistryOwnableFactory, + Enclave__factory as EnclaveFactory, + NaiveRegistryFilter__factory as NaiveRegistryFilterFactory, +} from "../types"; + +const { ethers, ignition, networkHelpers } = await network.connect(); +const { loadFixture, time, mine } = networkHelpers; describe("Enclave", function () { - async function setup() { + const THIRTY_DAYS_IN_SECONDS = 60 * 60 * 24 * 30; + const addressOne = "0x0000000000000000000000000000000000000001"; + const AddressTwo = "0x0000000000000000000000000000000000000002"; + + const encryptionSchemeId = + "0x2c2a814a0495f913a3a312fc4771e37552bc14f8a2d4075a08122d356f0849c6"; + const newEncryptionSchemeId = + "0x0000000000000000000000000000000000000000000000000000000000000002"; + + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + + const polynomial_degree = ethers.toBigInt(2048); + const plaintext_modulus = ethers.toBigInt(1032193); + const moduli = [ethers.toBigInt("18014398492704769")]; // 0x3FFFFFFF000001 + + const encodedE3ProgramParams = abiCoder.encode( + ["uint256", "uint256", "uint256[]"], + [polynomial_degree, plaintext_modulus, moduli], + ); + + const data = "0xda7a"; + const dataHash = ethers.keccak256(data); + const proof = "0x1337"; + + // Hash function used to compute the tree nodes. + const hash = (a: bigint, b: bigint) => poseidon2([a, b]); + + const setup = async () => { const [owner, notTheOwner] = await ethers.getSigners(); - if (!owner) throw new Error("Bad getSigners() output"); - if (!notTheOwner) throw new Error("Bad getSigners() output"); - const poseidon = await PoseidonT3Fixture(); - const registry = await deployCiphernodeRegistryFixture(); - const decryptionVerifier = await deployDecryptionVerifierFixture(); - const computeProvider = await deployComputeProviderFixture(); - const inputValidator = await deployInputValidatorFixture(); + const ownerAddress = await owner.getAddress(); - const e3Program = await deployE3ProgramFixture( - await inputValidator.getAddress(), + const enclaveContract = await ignition.deploy(EnclaveModule, { + parameters: { + Enclave: { + params: encodedE3ProgramParams, + owner: ownerAddress, + maxDuration: THIRTY_DAYS_IN_SECONDS, + registry: addressOne, + }, + }, + }); + + const enclaveAddress = await enclaveContract.enclave.getAddress(); + + const ciphernodeRegistry = await ignition.deploy( + MockCiphernodeRegistryModule, ); - const enclave = await deployEnclaveFixture( - owner.address, - await registry.getAddress(), - await poseidon.getAddress(), + const ciphernodeRegistryAddress = + await ciphernodeRegistry.mockCiphernodeRegistry.getAddress(); + + const naiveRegistryFilter = await ignition.deploy( + NaiveRegistryFilterModule, + { + parameters: { + NaiveRegistryFilter: { + ciphernodeRegistryAddress, + owner: ownerAddress, + }, + }, + }, ); - await enclave.setDecryptionVerifier( - encryptionSchemeId, - await decryptionVerifier.getAddress(), + const naiveRegistryFilterAddress = + await naiveRegistryFilter.naiveRegistryFilter.getAddress(); + + const enclave = EnclaveFactory.connect(enclaveAddress, owner); + const ciphernodeRegistryContract = CiphernodeRegistryOwnableFactory.connect( + ciphernodeRegistryAddress, + owner, ); + const naiveRegistryFilterContract = NaiveRegistryFilterFactory.connect( + naiveRegistryFilterAddress, + owner, + ); + const registryAddress = await enclave.ciphernodeRegistry(); + + if (registryAddress !== ciphernodeRegistryAddress) { + await enclave.setCiphernodeRegistry(ciphernodeRegistryAddress); + } + + const mockComputeProvider = await ignition.deploy( + mockComputeProviderModule, + ); + + const decryptionVerifier = await ignition.deploy( + MockDecryptionVerifierModule, + ); + + const inputValidator = await ignition.deploy(MockInputValidatorModule); - await enclave.enableE3Program(await e3Program.getAddress()); + const e3Program = await ignition.deploy(MockE3ProgramModule, { + parameters: { + MockE3Program: { + mockInputValidator: + await inputValidator.mockInputValidator.getAddress(), + }, + }, + }); + await enclave.enableE3Program(await e3Program.mockE3Program.getAddress()); await enclave.setE3ProgramsParams([encodedE3ProgramParams]); + await enclave.setDecryptionVerifier( + encryptionSchemeId, + await decryptionVerifier.mockDecryptionVerifier.getAddress(), + ); + + const request = { + filter: await naiveRegistryFilterContract.getAddress(), + threshold: [2, 2] as [number, number], + startTime: [await time.latest(), (await time.latest()) + 100] as [ + number, + number, + ], + duration: time.duration.days(30), + e3Program: await e3Program.mockE3Program.getAddress(), + e3ProgramParams: encodedE3ProgramParams, + computeProviderParams: abiCoder.encode( + ["address"], + [await decryptionVerifier.mockDecryptionVerifier.getAddress()], + ), + }; return { - owner, - notTheOwner, enclave, - poseidon, + ciphernodeRegistryContract, + naiveRegistryFilterContract, mocks: { - e3Program, - decryptionVerifier, - inputValidator, - computeProvider, - registry, - }, - request: { - filter: FilterOkay, - threshold: [2, 2] as [number, number], - startTime: [await time.latest(), (await time.latest()) + 100] as [ - number, - number, - ], - duration: time.duration.days(30), - e3Program: await e3Program.getAddress(), - e3ProgramParams: encodedE3ProgramParams, - computeProviderParams: abiCoder.encode( - ["address"], - [await decryptionVerifier.getAddress()], - ), + decryptionVerifier: decryptionVerifier.mockDecryptionVerifier, + inputValidator: inputValidator.mockInputValidator, + e3Program: e3Program.mockE3Program, + mockComputeProvider: mockComputeProvider.mockComputeProvider, }, + request, + owner, + notTheOwner, }; - } + }; describe("constructor / initialize()", function () { it("correctly sets owner", async function () { - const { owner, enclave } = await loadFixture(setup); - expect(await enclave.owner()).to.equal(owner.address); + const { enclave, owner } = await loadFixture(setup); + expect(await enclave.owner()).to.equal(await owner.getAddress()); }); it("correctly sets ciphernodeRegistry address", async function () { - const { mocks, enclave } = await loadFixture(setup); + const { enclave, ciphernodeRegistryContract } = await loadFixture(setup); expect(await enclave.ciphernodeRegistry()).to.equal( - await mocks.registry.getAddress(), + await ciphernodeRegistryContract.getAddress(), ); }); @@ -134,7 +188,12 @@ describe("Enclave", function () { describe("setMaxDuration()", function () { it("reverts if not called by owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); - await expect(enclave.connect(notTheOwner).setMaxDuration(1)) + + await expect( + enclave + .connect(notTheOwner) + .setMaxDuration(1, { from: await notTheOwner.getAddress() }), + ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); @@ -166,21 +225,25 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); + it("reverts if given address(0)", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.setCiphernodeRegistry(ethers.ZeroAddress)) .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(ethers.ZeroAddress); }); + it("reverts if given address is the same as the current ciphernodeRegistry", async function () { - const { - enclave, - mocks: { registry }, - } = await loadFixture(setup); - await expect(enclave.setCiphernodeRegistry(registry)) + const { enclave, ciphernodeRegistryContract } = await loadFixture(setup); + await expect( + enclave.setCiphernodeRegistry( + await ciphernodeRegistryContract.getAddress(), + ), + ) .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") - .withArgs(registry); + .withArgs(await ciphernodeRegistryContract.getAddress()); }); + it("sets ciphernodeRegistry correctly", async function () { const { enclave } = await loadFixture(setup); @@ -188,12 +251,14 @@ describe("Enclave", function () { await enclave.setCiphernodeRegistry(AddressTwo); expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); + it("returns true if ciphernodeRegistry is set successfully", async function () { const { enclave } = await loadFixture(setup); const result = await enclave.setCiphernodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); + it("emits CiphernodeRegistrySet event", async function () { const { enclave } = await loadFixture(setup); @@ -204,15 +269,6 @@ describe("Enclave", function () { }); describe("setE3ProgramsParams()", function () { - const polynomial_degree = ethers.toBigInt(2048); - const plaintext_modulus = ethers.toBigInt(1032193); - const moduli = [ethers.toBigInt("18014398492704769")]; // 0x3FFFFFFF000001 - - const encodedE3ProgramParams = ethers.AbiCoder.defaultAbiCoder().encode( - ["uint256", "uint256", "uint256[]"], - [polynomial_degree, plaintext_modulus, moduli], - ); - const encodedE3ProgramsParams = [encodedE3ProgramParams]; it("reverts if not called by owner", async function () { @@ -274,11 +330,14 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(1); }); + it("returns correct E3 details", async function () { - const { enclave, request, mocks } = await loadFixture(setup); + const { enclave, request, mocks, naiveRegistryFilterContract } = + await loadFixture(setup); + await enclave.request( { - filter: request.filter, + filter: await naiveRegistryFilterContract.getAddress(), threshold: request.threshold, startWindow: request.startTime, duration: request.duration, @@ -314,6 +373,7 @@ describe("Enclave", function () { await mocks.decryptionVerifier.getAddress(), ); }); + it("returns false if encryption scheme is not enabled", async function () { const { enclave } = await loadFixture(setup); expect( @@ -324,7 +384,7 @@ describe("Enclave", function () { describe("setDecryptionVerifier()", function () { it("reverts if caller is not owner", async function () { - const { enclave, notTheOwner, mocks } = await loadFixture(setup); + const { enclave, mocks, notTheOwner } = await loadFixture(setup); await expect( enclave @@ -337,6 +397,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); + it("reverts if encryption scheme is already enabled", async function () { const { enclave, mocks } = await loadFixture(setup); @@ -349,6 +410,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); + it("enabled decryption verifier", async function () { const { enclave, mocks } = await loadFixture(setup); @@ -362,6 +424,7 @@ describe("Enclave", function () { await enclave.getDecryptionVerifier(newEncryptionSchemeId), ).to.equal(await mocks.decryptionVerifier.getAddress()); }); + it("returns true if decryption verifier is enabled successfully", async function () { const { enclave, mocks } = await loadFixture(setup); @@ -371,6 +434,7 @@ describe("Enclave", function () { ); expect(result).to.be.true; }); + it("emits EncryptionSchemeEnabled", async function () { const { enclave, mocks } = await loadFixture(setup); @@ -431,9 +495,9 @@ describe("Enclave", function () { describe("enableE3Program()", function () { it("reverts if not called by owner", async function () { const { - notTheOwner, enclave, mocks: { e3Program }, + notTheOwner, } = await loadFixture(setup); await expect(enclave.connect(notTheOwner).enableE3Program(e3Program)) @@ -474,9 +538,9 @@ describe("Enclave", function () { describe("disableE3Program()", function () { it("reverts if not called by owner", async function () { const { - notTheOwner, enclave, mocks: { e3Program }, + notTheOwner, } = await loadFixture(setup); await expect(enclave.connect(notTheOwner).disableE3Program(e3Program)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") @@ -646,7 +710,7 @@ describe("Enclave", function () { await expect( enclave.request( { - filter: FilterFail, + filter: AddressTwo, threshold: request.threshold, startWindow: request.startTime, duration: request.duration, @@ -737,8 +801,10 @@ describe("Enclave", function () { { value: 10 }, ); - await expect(enclave.getE3(0)).to.not.be.reverted; - await expect(enclave.activate(0, ethers.ZeroHash)).to.not.be.reverted; + await expect(enclave.getE3(0)).to.not.be.revert(ethers); + await expect(enclave.activate(0, ethers.ZeroHash)).to.not.be.revert( + ethers, + ); await expect(enclave.activate(0, ethers.ZeroHash)) .to.be.revertedWithCustomError(enclave, "E3AlreadyActivated") .withArgs(0); @@ -844,7 +910,8 @@ describe("Enclave", function () { ).to.be.revertedWithCustomError(enclave, "E3Expired"); }); it("reverts if ciphernodeRegistry does not return a public key", async function () { - const { enclave, request } = await loadFixture(setup); + const { enclave, request, naiveRegistryFilterContract } = + await loadFixture(setup); await enclave.request( { @@ -860,24 +927,27 @@ describe("Enclave", function () { ); const prevRegistry = await enclave.ciphernodeRegistry(); - const nextRegistry = await deployCiphernodeRegistryFixture( - "MockCiphernodeRegistryEmptyKey", - ); + + const reg = await ignition.deploy(MockCiphernodeRegistryEmptyKeyModule); + const nextRegistry = + await reg.mockCiphernodeRegistryEmptyKey.getAddress(); await enclave.setCiphernodeRegistry(nextRegistry); + await naiveRegistryFilterContract.setRegistry(nextRegistry); + await expect( enclave.activate(0, ethers.ZeroHash), ).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); await enclave.setCiphernodeRegistry(prevRegistry); - await expect(enclave.activate(0, ethers.ZeroHash)).to.not.be.reverted; + await expect(enclave.activate(0, ethers.ZeroHash)).not.to.be.revert( + ethers, + ); }); + it("sets committeePublicKey correctly", async () => { - const { - enclave, - request, - mocks: { registry }, - } = await loadFixture(setup); + const { enclave, request, ciphernodeRegistryContract } = + await loadFixture(setup); await enclave.request( { @@ -893,7 +963,8 @@ describe("Enclave", function () { ); const e3Id = 0; - const publicKey = await registry.committeePublicKey(e3Id); + const publicKey = + await ciphernodeRegistryContract.committeePublicKey(e3Id); let e3 = await enclave.getE3(e3Id); expect(e3.committeePublicKey).to.not.equal(ethers.keccak256(publicKey)); @@ -943,9 +1014,10 @@ describe("Enclave", function () { const e3Id = 0; - await expect(enclave.activate(e3Id, ethers.ZeroHash)) - .to.emit(enclave, "E3Activated") - .withArgs(e3Id, anyValue, ethers.ZeroHash); + await expect(enclave.activate(e3Id, ethers.ZeroHash)).to.emit( + enclave, + "E3Activated", + ); }); }); @@ -974,9 +1046,9 @@ describe("Enclave", function () { { value: 10 }, ); - const inputData = abiCoder.encode(["bytes32"], [ZeroHash]); + const inputData = abiCoder.encode(["bytes32"], [ethers.ZeroHash]); - await expect(enclave.getE3(0)).to.not.be.reverted; + await expect(enclave.getE3(0)).to.not.be.revert(ethers); await expect(enclave.publishInput(0, inputData)) .to.be.revertedWithCustomError(enclave, "E3NotActivated") .withArgs(0); @@ -1027,7 +1099,7 @@ describe("Enclave", function () { await mine(2, { interval: request.duration }); await expect( - enclave.publishInput(0, ZeroHash), + enclave.publishInput(0, ethers.ZeroHash), ).to.be.revertedWithCustomError(enclave, "InputDeadlinePassed"); }); diff --git a/packages/enclave-contracts/test/fixtures/CiphernodeRegistryOwnable.fixture.ts b/packages/enclave-contracts/test/fixtures/CiphernodeRegistryOwnable.fixture.ts deleted file mode 100644 index 720c5e686c..0000000000 --- a/packages/enclave-contracts/test/fixtures/CiphernodeRegistryOwnable.fixture.ts +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { CiphernodeRegistryOwnable__factory } from "../../types"; - -export async function deployCiphernodeRegistryOwnableFixture( - owner: string, - enclave: string, - poseidonT3: string, - name?: string, -) { - const [signer] = await ethers.getSigners(); - const deployment = await ( - await ethers.getContractFactory(name || "CiphernodeRegistryOwnable", { - libraries: { - PoseidonT3: poseidonT3, - }, - }) - ).deploy(owner, enclave); - - return CiphernodeRegistryOwnable__factory.connect( - await deployment.getAddress(), - signer, - ); -} diff --git a/packages/enclave-contracts/test/fixtures/Enclave.fixture.ts b/packages/enclave-contracts/test/fixtures/Enclave.fixture.ts deleted file mode 100644 index cfc4bcafc8..0000000000 --- a/packages/enclave-contracts/test/fixtures/Enclave.fixture.ts +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; - -export async function deployEnclaveFixture( - owner: string, - registry: string, - poseidonT3: string, - maxDuration?: number, -) { - const [signer] = await ethers.getSigners(); - const polynomial_degree = ethers.toBigInt(2048); - const plaintext_modulus = ethers.toBigInt(1032193); - const moduli = [ethers.toBigInt("18014398492704769")]; // 0x3FFFFFFF000001 - - // Encode just the struct (NOT the function selector) - const encoded = ethers.AbiCoder.defaultAbiCoder().encode( - ["uint256", "uint256", "uint256[]"], - [polynomial_degree, plaintext_modulus, moduli], - ); - - const deployment = await ( - await ethers.getContractFactory("Enclave", { - libraries: { - PoseidonT3: poseidonT3, - }, - }) - ).deploy(owner, registry, maxDuration || 60 * 60 * 24 * 30, [encoded]); - - return Enclave__factory.connect(await deployment.getAddress(), signer); -} diff --git a/packages/enclave-contracts/test/fixtures/MockCiphernodeRegistry.fixture.ts b/packages/enclave-contracts/test/fixtures/MockCiphernodeRegistry.fixture.ts deleted file mode 100644 index 1a9ddabb56..0000000000 --- a/packages/enclave-contracts/test/fixtures/MockCiphernodeRegistry.fixture.ts +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { MockCiphernodeRegistry__factory } from "../../types"; - -export async function deployCiphernodeRegistryFixture(name?: string) { - const [signer] = await ethers.getSigners(); - const deployment = await ( - await ethers.getContractFactory(name || "MockCiphernodeRegistry") - ).deploy(); - - return MockCiphernodeRegistry__factory.connect( - await deployment.getAddress(), - signer!.provider, - ); -} diff --git a/packages/enclave-contracts/test/fixtures/MockComputeProvider.fixture.ts b/packages/enclave-contracts/test/fixtures/MockComputeProvider.fixture.ts deleted file mode 100644 index ea8273fac9..0000000000 --- a/packages/enclave-contracts/test/fixtures/MockComputeProvider.fixture.ts +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { MockComputeProvider__factory } from "../../types/factories/contracts/test/MockComputeProvider__factory"; - -export async function deployComputeProviderFixture() { - const deployment = await ( - await ethers.getContractFactory("MockComputeProvider") - ).deploy(); - - return MockComputeProvider__factory.connect(await deployment.getAddress()); -} diff --git a/packages/enclave-contracts/test/fixtures/MockDecryptionVerifier.fixture.ts b/packages/enclave-contracts/test/fixtures/MockDecryptionVerifier.fixture.ts deleted file mode 100644 index 83dcbb1e1a..0000000000 --- a/packages/enclave-contracts/test/fixtures/MockDecryptionVerifier.fixture.ts +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { MockDecryptionVerifier__factory } from "../../types/factories/contracts/test/MockDecryptionVerifier__factory"; - -export async function deployDecryptionVerifierFixture() { - const deployment = await ( - await ethers.getContractFactory("MockDecryptionVerifier") - ).deploy(); - return MockDecryptionVerifier__factory.connect(await deployment.getAddress()); -} diff --git a/packages/enclave-contracts/test/fixtures/MockE3Program.fixture.ts b/packages/enclave-contracts/test/fixtures/MockE3Program.fixture.ts deleted file mode 100644 index cafa5a0429..0000000000 --- a/packages/enclave-contracts/test/fixtures/MockE3Program.fixture.ts +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { MockE3Program__factory } from "../../types/factories/contracts/test/MockE3Program__factory"; - -export async function deployE3ProgramFixture(inputValidator: string) { - const deployment = await ( - await ethers.getContractFactory("MockE3Program") - ).deploy(inputValidator); - return MockE3Program__factory.connect(await deployment.getAddress()); -} diff --git a/packages/enclave-contracts/test/fixtures/MockInputValidator.fixture.ts b/packages/enclave-contracts/test/fixtures/MockInputValidator.fixture.ts deleted file mode 100644 index 0d47c02c4a..0000000000 --- a/packages/enclave-contracts/test/fixtures/MockInputValidator.fixture.ts +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { MockInputValidator__factory } from "../../types/factories/contracts/test/MockInputValidator__factory"; - -export async function deployInputValidatorFixture() { - const deployment = await ( - await ethers.getContractFactory("MockInputValidator") - ).deploy(); - return MockInputValidator__factory.connect(await deployment.getAddress()); -} diff --git a/packages/enclave-contracts/test/fixtures/NaiveRegistryFilter.fixture.ts b/packages/enclave-contracts/test/fixtures/NaiveRegistryFilter.fixture.ts deleted file mode 100644 index 7538cbe9c6..0000000000 --- a/packages/enclave-contracts/test/fixtures/NaiveRegistryFilter.fixture.ts +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { NaiveRegistryFilter__factory } from "../../types"; - -export async function naiveRegistryFilterFixture( - owner: string, - registry: string, - name?: string, -) { - const [signer] = await ethers.getSigners(); - const deployment = await ( - await ethers.getContractFactory(name || "NaiveRegistryFilter") - ).deploy(owner, registry); - - return NaiveRegistryFilter__factory.connect( - await deployment.getAddress(), - signer, - ); -} diff --git a/packages/enclave-contracts/test/fixtures/PoseidonT3.fixture.ts b/packages/enclave-contracts/test/fixtures/PoseidonT3.fixture.ts deleted file mode 100644 index 2193987b93..0000000000 --- a/packages/enclave-contracts/test/fixtures/PoseidonT3.fixture.ts +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import { ethers } from "hardhat"; - -import { PoseidonT3__factory } from "../../types"; - -export async function PoseidonT3Fixture(name?: string) { - const [signer] = await ethers.getSigners(); - if (!signer) throw new Error("Bad getSigners output"); - const deployment = await ( - await ethers.getContractFactory(name || "PoseidonT3") - ).deploy(); - - return PoseidonT3__factory.connect( - await deployment.getAddress(), - signer.provider, - ); -} diff --git a/packages/enclave-contracts/test/fixtures/pubkey.bin b/packages/enclave-contracts/test/fixtures/pubkey.bin deleted file mode 100644 index ecc1d29341..0000000000 Binary files a/packages/enclave-contracts/test/fixtures/pubkey.bin and /dev/null differ diff --git a/packages/enclave-contracts/tsconfig.json b/packages/enclave-contracts/tsconfig.json index 7bfa765c31..af22e24677 100644 --- a/packages/enclave-contracts/tsconfig.json +++ b/packages/enclave-contracts/tsconfig.json @@ -1,11 +1,22 @@ { - "extends": "@enclave-e3/config/tsconfig.json", - "include": ["tasks/**/*", "test/**/*", "deploy/**/*", "types/**/*"], - "exclude": ["node_modules", "dist"], "compilerOptions": { - "module": "commonjs", - "moduleResolution": "node", - "incremental": true, - "tsBuildInfoFile": "./dist/.tsbuildinfo" - } + "lib": ["es2023"], + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist", + "declaration": true, + "declarationMap": true + }, + "include": [ + "hardhat.config.ts", + "scripts/**/*.ts", + "ignition/modules/**/*.ts", + "test/**/*.ts", + "tasks/**/*.ts" + ], + "exclude": ["node_modules", "dist", "types"] } diff --git a/packages/enclave-contracts/tsup.config.mjs b/packages/enclave-contracts/tsup.config.mjs deleted file mode 100644 index f6d26e5b58..0000000000 --- a/packages/enclave-contracts/tsup.config.mjs +++ /dev/null @@ -1,10 +0,0 @@ -import { baseConfig } from "@enclave-e3/config/tsup"; -import { defineConfig } from "tsup"; - -export default defineConfig({ - ...baseConfig, - entry: ["deploy/enclave.ts", "deploy/mocks.ts", "types/index.ts"], - include: ["./deploy/**/*.ts", "./types/**/*.ts"], - external: [/^mocha/, /^ts-node/, "hardhat-deploy"], - format: ["esm", "cjs"], -}); diff --git a/packages/enclave-sdk/package.json b/packages/enclave-sdk/package.json index e48a16dfa3..a050560396 100644 --- a/packages/enclave-sdk/package.json +++ b/packages/enclave-sdk/package.json @@ -20,7 +20,7 @@ "access": "public" }, "scripts": { - "prebuild": "cd ../enclave-contracts && pnpm compile:ts && cd ../../crates/wasm && pnpm build", + "prebuild": "cd ../enclave-contracts && pnpm build && cd ../../crates/wasm && pnpm build", "build": "tsup", "dev": "tsup --watch", "clean": "rm -rf dist", diff --git a/packages/enclave-sdk/src/contract-client.ts b/packages/enclave-sdk/src/contract-client.ts index bebadd9fbd..e1df26b347 100644 --- a/packages/enclave-sdk/src/contract-client.ts +++ b/packages/enclave-sdk/src/contract-client.ts @@ -115,8 +115,7 @@ export class ContractClient { e3Program, e3ProgramParams, computeProviderParams, - } - ], + }], account, value: value || BigInt(0), gas: gasLimit, diff --git a/packages/enclave-sdk/tsup.config.js b/packages/enclave-sdk/tsup.config.js index c3eba93d7b..076ad3aed8 100644 --- a/packages/enclave-sdk/tsup.config.js +++ b/packages/enclave-sdk/tsup.config.js @@ -17,7 +17,7 @@ export default defineConfig([ }), esbuildOptions: (options) => { options.alias = { - "@enclave-e3/wasm/init": "../../../crates/wasm/init_node.js", + "@enclave-e3/wasm/init": "../../crates/wasm/init_node.js", }; }, }, @@ -30,7 +30,7 @@ export default defineConfig([ }), esbuildOptions: (options) => { options.alias = { - "@enclave-e3/wasm/init": "../../../crates/wasm/init_node.cjs", + "@enclave-e3/wasm/init": "../../crates/wasm/init_node.cjs", }; }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf4bfadcca..94f4449cb3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,33 +88,18 @@ importers: '@enclave-e3/config': specifier: ^0.0.10-test version: 0.0.10-test(tsup@8.5.0(@microsoft/api-extractor@7.52.11(@types/node@22.7.5))(@swc/core@1.13.5)(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.8.3)(yaml@2.8.1)) - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^2.0.0 - version: 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.0 - version: 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-foundry': - specifier: ^1.1.2 - version: 1.2.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + version: 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ignition': - specifier: ^0.15.5 - version: 0.15.13(@nomicfoundation/hardhat-verify@2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - '@nomicfoundation/hardhat-ignition-ethers': - specifier: ^0.15.0 - version: 0.15.14(fcdc0daa2d57f78852817b38ea974238) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.0 - version: 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: ^3.0.0 + version: 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@nomicfoundation/hardhat-toolbox': specifier: ^5.0.0 - version: 5.0.0(199633c01e7f1dcb215c469e4940f39b) - '@nomicfoundation/hardhat-verify': - specifier: ^2.0.0 - version: 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/ignition-core': - specifier: ^0.15.5 - version: 0.15.13(bufferutil@4.0.9)(utf-8-validate@5.0.10) + version: 5.0.0(a2c664a2c86c3ae5dd9cd312b280c590) + '@nomicfoundation/hardhat-toolbox-viem': + specifier: ^5.0.0 + version: 5.0.0(57ef2920aa19fe9eb07b2e80a48eb774) '@playwright/test': specifier: 1.52.0 version: 1.52.0 @@ -129,7 +114,7 @@ importers: version: 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^9.0.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) + version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) '@types/chai': specifier: ^4.2.0 version: 4.3.20 @@ -148,21 +133,24 @@ importers: ethers: specifier: ^6.15.0 version: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + forge-std: + specifier: github:foundry-rs/forge-std#v1.9.4 + version: https://codeload.github.com/foundry-rs/forge-std/tar.gz/1eea5bae12ae557d589f9f0f0edae2faa47cb262 hardhat: - specifier: ^2.22.10 - version: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + specifier: ^3.0.1 + version: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) hardhat-deploy: specifier: ^0.12.4 version: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) hardhat-gas-reporter: specifier: ^1.0.8 - version: 1.0.10(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + version: 1.0.10(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) playwright: specifier: 1.52.0 version: 1.52.0 solidity-coverage: specifier: ^0.8.1 - version: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + version: 0.8.16(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) @@ -339,21 +327,30 @@ importers: '@enclave-e3/config': specifier: workspace:* version: link:../enclave-config - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^2.0.2 - version: 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.5 - version: 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: '4' + version: 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ethers-chai-matchers': + specifier: ^3.0.0 + version: 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition': + specifier: ^3.0.0 + version: 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition-ethers': + specifier: ^3.0.1 + version: 3.0.2(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.10 - version: 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-toolbox': - specifier: ^4.0.0 - version: 4.0.0(4308261da56a39dba1593c5e7639385e) + specifier: '3' + version: 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-toolbox-mocha-ethers': + specifier: 3.0.0 + version: 3.0.0(6b85ed473db2330ad75256729be2beb8) + '@nomicfoundation/hardhat-typechain': + specifier: '3' + version: 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3) '@nomicfoundation/hardhat-verify': - specifier: ^2.0.2 - version: 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: '3' + version: 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.3.0 @@ -363,20 +360,20 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: ^4.3.0 version: 4.3.0(prettier@3.6.2) - '@typechain/ethers-v6': - specifier: ^0.5.1 - version: 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': specifier: ^9.1.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) + version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) '@types/chai': - specifier: ^4.3.11 + specifier: ^4.3.20 version: 4.3.20 + '@types/chai-as-promised': + specifier: ^8.0.2 + version: 8.0.2 '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 '@types/mocha': - specifier: ^10.0.6 + specifier: ^10.0.10 version: 10.0.10 '@types/node': specifier: 22.7.5 @@ -394,8 +391,8 @@ importers: specifier: 2.0.0 version: 2.0.0 chai: - specifier: ^4.3.10 - version: 4.5.0 + specifier: ^5.3.3 + version: 5.3.3 cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -409,26 +406,26 @@ importers: specifier: ^9.1.0 version: 9.1.2(eslint@8.57.1) ethers: - specifier: ^6.9.0 + specifier: ^6.15.0 version: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + forge-std: + specifier: github:foundry-rs/forge-std#v1.9.4 + version: https://codeload.github.com/foundry-rs/forge-std/tar.gz/1eea5bae12ae557d589f9f0f0edae2faa47cb262 fs-extra: specifier: ^11.2.0 version: 11.3.1 hardhat: - specifier: ^2.22.0 - version: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-deploy: - specifier: ^0.12.1 - version: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + specifier: ^3.0.1 + version: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) hardhat-gas-reporter: specifier: ^2.2.0 - version: 2.3.0(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(utf-8-validate@5.0.10) + version: 2.3.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) lodash: specifier: ^4.17.21 version: 4.17.21 mocha: - specifier: ^10.2.0 - version: 10.8.2 + specifier: ^11.7.1 + version: 11.7.2 poseidon-lite: specifier: ^0.3.0 version: 0.3.0 @@ -452,7 +449,7 @@ importers: version: 0.1.0(prettier-plugin-solidity@1.4.3(prettier@3.6.2))(prettier@3.6.2) solidity-coverage: specifier: ^0.8.5 - version: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + version: 0.8.16(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ts-generator: specifier: ^0.1.1 version: 0.1.1 @@ -564,33 +561,36 @@ importers: specifier: ^18.0.0 version: 18.0.0 devDependencies: - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^2.0.0 - version: 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.5 - version: 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: '4' + version: 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ethers-chai-matchers': + specifier: ^3.0.0 + version: 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition': + specifier: ^3.0.0 + version: 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition-ethers': + specifier: ^3.0.1 + version: 3.0.2(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.10 - version: 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-toolbox': - specifier: ^4.0.0 - version: 4.0.0(954e9d9570193eb16113ebf9d0b86657) + specifier: '3' + version: 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-toolbox-mocha-ethers': + specifier: 3.0.0 + version: 3.0.0(90f84ad61b06116a79b8c39a263ea2f9) + '@nomicfoundation/hardhat-typechain': + specifier: '3' + version: 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3) '@nomicfoundation/hardhat-verify': - specifier: ^2.0.2 - version: 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + specifier: '3' + version: 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': specifier: 5.3.0 version: 5.3.0 '@risc0/ethereum': specifier: file:lib/risc0-ethereum version: file:templates/default/lib/risc0-ethereum - '@typechain/ethers-v6': - specifier: ^0.5.0 - version: 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) - '@typechain/hardhat': - specifier: ^9.1.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) '@types/chai': specifier: ^4.2.0 version: 4.3.20 @@ -622,35 +622,29 @@ importers: specifier: ^5.1.0 version: 5.1.0 hardhat: - specifier: ^2.22.10 - version: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-deploy: - specifier: ^0.12.1 - version: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat-gas-reporter: - specifier: ^1.0.8 - version: 1.0.10(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + specifier: ^3.0.1 + version: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) poseidon-lite: specifier: ^0.3.0 version: 0.3.0 solidity-coverage: specifier: ^0.8.0 - version: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + version: 0.8.16(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) tsx: specifier: ^4.20.3 version: 4.20.5 - typechain: - specifier: ^8.3.0 - version: 8.3.2(typescript@5.8.3) typed-rpc: specifier: ^6.1.1 version: 6.1.1 typescript: specifier: 5.8.3 version: 5.8.3 + vitest: + specifier: ^1.6.1 + version: 1.6.1(@types/node@22.7.5) wait-on: specifier: ^8.0.3 version: 8.0.4 @@ -748,6 +742,18 @@ importers: packages: + '@actions/core@1.11.1': + resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} + + '@actions/exec@1.1.1': + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + + '@actions/http-client@2.2.3': + resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} + + '@actions/io@1.1.3': + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + '@adraffy/ens-normalize@1.10.1': resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} @@ -2005,11 +2011,6 @@ packages: engines: {node: '>=14'} hasBin: true - '@ethereumjs/rlp@5.0.2': - resolution: {integrity: sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==} - engines: {node: '>=18'} - hasBin: true - '@ethereumjs/tx@4.2.0': resolution: {integrity: sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==} engines: {node: '>=14'} @@ -2018,10 +2019,6 @@ packages: resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} engines: {node: '>=14'} - '@ethereumjs/util@9.1.0': - resolution: {integrity: sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog==} - engines: {node: '>=18'} - '@ethersproject/abi@5.8.0': resolution: {integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==} @@ -2736,37 +2733,37 @@ packages: '@noir-lang/types@1.0.0-beta.3': resolution: {integrity: sha512-BPOmf0qDiTn4wH1Lo7mHa67GTQFueIVaDUcUb+N9+ALiXC5nVU8HrzWmx1yvZB64ZiCEy7yPdNEaNrszSrE2fg==} - '@nomicfoundation/edr-darwin-arm64@0.11.3': - resolution: {integrity: sha512-w0tksbdtSxz9nuzHKsfx4c2mwaD0+l5qKL2R290QdnN9gi9AV62p9DHkOgfBdyg6/a6ZlnQqnISi7C9avk/6VA==} + '@nomicfoundation/edr-darwin-arm64@0.12.0-next.5': + resolution: {integrity: sha512-LfDxE/Q+wsToSL17Rf6HNaqfp3v4G9AGwjzfCa3momYw9QhMiELfB4nPm93qt3pwwuiCCqqpdURFdC8oYmVHfg==} engines: {node: '>= 18'} - '@nomicfoundation/edr-darwin-x64@0.11.3': - resolution: {integrity: sha512-QR4jAFrPbOcrO7O2z2ESg+eUeIZPe2bPIlQYgiJ04ltbSGW27FblOzdd5+S3RoOD/dsZGKAvvy6dadBEl0NgoA==} + '@nomicfoundation/edr-darwin-x64@0.12.0-next.5': + resolution: {integrity: sha512-jKTBN90XOTFkeg0BgxmXemvUUuC0fr2vwekMcxLhW2zb0E6oO/DM5ApSz4KoQhefVZCOFFvmj0Za5Cgr27accg==} engines: {node: '>= 18'} - '@nomicfoundation/edr-linux-arm64-gnu@0.11.3': - resolution: {integrity: sha512-Ktjv89RZZiUmOFPspuSBVJ61mBZQ2+HuLmV67InNlh9TSUec/iDjGIwAn59dx0bF/LOSrM7qg5od3KKac4LJDQ==} + '@nomicfoundation/edr-linux-arm64-gnu@0.12.0-next.5': + resolution: {integrity: sha512-aBe22ybgRdgSCVBtw5x8w25wwHhQa1B1mrcmHeFadW5lBM4thOwpq4xeNcdRhID7ZSkJvRTCe9KA1yCn2EYdbw==} engines: {node: '>= 18'} - '@nomicfoundation/edr-linux-arm64-musl@0.11.3': - resolution: {integrity: sha512-B3sLJx1rL2E9pfdD4mApiwOZSrX0a/KQSBWdlq1uAhFKqkl00yZaY4LejgZndsJAa4iKGQJlGnw4HCGeVt0+jA==} + '@nomicfoundation/edr-linux-arm64-musl@0.12.0-next.5': + resolution: {integrity: sha512-168VcV9HcUY6rRmZNb2wHWWQJ82BZmu4if17MnQSeqT/u77hObjx4P7rfFpcOxfnuEbP2NEgAZsA7uU2bMcRMQ==} engines: {node: '>= 18'} - '@nomicfoundation/edr-linux-x64-gnu@0.11.3': - resolution: {integrity: sha512-D/4cFKDXH6UYyKPu6J3Y8TzW11UzeQI0+wS9QcJzjlrrfKj0ENW7g9VihD1O2FvXkdkTjcCZYb6ai8MMTCsaVw==} + '@nomicfoundation/edr-linux-x64-gnu@0.12.0-next.5': + resolution: {integrity: sha512-C0N9zBEMGwYO5Is9dYuvM2Bl/0y1ornF6xRmnaaMOEf9y6grjC84Ip33fnySNG4nGcjHMYrS2RBC/Lm+rg4BcA==} engines: {node: '>= 18'} - '@nomicfoundation/edr-linux-x64-musl@0.11.3': - resolution: {integrity: sha512-ergXuIb4nIvmf+TqyiDX5tsE49311DrBky6+jNLgsGDTBaN1GS3OFwFS8I6Ri/GGn6xOaT8sKu3q7/m+WdlFzg==} + '@nomicfoundation/edr-linux-x64-musl@0.12.0-next.5': + resolution: {integrity: sha512-BqCg+I4/r833BH4bVA/0oAYTvfg7GHpUq0DTRqaAwTD1bWTD48rIEtKBYZ6KEDQNB3NQEi5CMz50G9ziteaq0A==} engines: {node: '>= 18'} - '@nomicfoundation/edr-win32-x64-msvc@0.11.3': - resolution: {integrity: sha512-snvEf+WB3OV0wj2A7kQ+ZQqBquMcrozSLXcdnMdEl7Tmn+KDCbmFKBt3Tk0X3qOU4RKQpLPnTxdM07TJNVtung==} + '@nomicfoundation/edr-win32-x64-msvc@0.12.0-next.5': + resolution: {integrity: sha512-5bp+w+dVxe5vxzQY0N+R1wuk6heCgSKqPLz5mjiU5SP/LtynF7mV2siXXCi+NGOM3sV04oUzLfR8K+c83Za5sw==} engines: {node: '>= 18'} - '@nomicfoundation/edr@0.11.3': - resolution: {integrity: sha512-kqILRkAd455Sd6v8mfP3C1/0tCOynJWY+Ir+k/9Boocu2kObCrsFgG+ZWB7fSBVdd9cPVSNrnhWS+V+PEo637g==} - engines: {node: '>= 18'} + '@nomicfoundation/edr@0.12.0-next.5': + resolution: {integrity: sha512-VhjH0OyKGtWqGeOMGICGsj2l0+7SyQWXp00wuY0hkG+vt1XH2G404L0CK9+qWEPcoZu9/LFcVGVs+Bb1XWvDPA==} + engines: {node: '>= 20'} '@nomicfoundation/hardhat-chai-matchers@2.1.0': resolution: {integrity: sha512-GPhBNafh1fCnVD9Y7BYvoLnblnvfcq3j8YDbO1gGe/1nOFWzGmV7gFu5DkwFXF+IpYsS+t96o9qc/mPu3V3Vfw==} @@ -2776,57 +2773,106 @@ packages: ethers: ^6.14.0 hardhat: ^2.26.0 + '@nomicfoundation/hardhat-errors@3.0.1': + resolution: {integrity: sha512-qXzTDmND5aNSolxms6shuLlPK8+rugKjDsLb1BRVAYnZfPBCIc52v8nX2HEW+/qBRp3YMZVDyJVrhud+Uby2JQ==} + + '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.0': + resolution: {integrity: sha512-IhDOUXv5+7cH1b8X5TX2qr2jLsMPjboFH/jXh7j090PbYWCRGwzdG3Olzzmd1X1WWpkw16nnz91+6pXuLpbQkw==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^4.0.0 + chai: ^5.1.2 + ethers: ^6.14.0 + hardhat: ^3.0.0 + '@nomicfoundation/hardhat-ethers@3.1.0': resolution: {integrity: sha512-jx6fw3Ms7QBwFGT2MU6ICG292z0P81u6g54JjSV105+FbTZOF4FJqPksLfDybxkkOeq28eDxbqq7vpxRYyIlxA==} peerDependencies: ethers: ^6.14.0 hardhat: ^2.26.0 - '@nomicfoundation/hardhat-foundry@1.2.0': - resolution: {integrity: sha512-2AJQLcWnUk/iQqHDVnyOadASKFQKF1PhNtt1cONEQqzUPK+fqME1IbP+EKu+RkZTRcyc4xqUMaB0sutglKRITg==} + '@nomicfoundation/hardhat-ethers@4.0.0': + resolution: {integrity: sha512-xLu5s9BJDufI9mP2I9IZYYAmDfoSCNZsZkeu+lw2fflpnqxYmg0NROlrJrYAIwGiY3VRc/JCuh19IQDKF/S1pA==} peerDependencies: - hardhat: ^2.26.0 + hardhat: ^3.0.0 - '@nomicfoundation/hardhat-ignition-ethers@0.15.14': - resolution: {integrity: sha512-eq+5n+c1DW18/Xp8/QrHBBvG5QaKUxYF/byol4f1jrnZ1zAy0OrqEa/oaNFWchhpLalX7d7suk/2EL0PbT0CDQ==} + '@nomicfoundation/hardhat-ignition-ethers@3.0.2': + resolution: {integrity: sha512-4Kv2K94SnYrLM2DEhfEv6WMMbA68wATzYjwzTMvpmbsLsjcdJe9MLo9mohTJt2Ck8g04/Mq1/Q0qwK0//pYdog==} peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.1.0 - '@nomicfoundation/hardhat-ignition': ^0.15.13 - '@nomicfoundation/ignition-core': ^0.15.13 + '@nomicfoundation/hardhat-ethers': ^4.0.0 + '@nomicfoundation/hardhat-ignition': ^3.0.2 + '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/ignition-core': ^3.0.2 ethers: ^6.14.0 - hardhat: ^2.26.0 + hardhat: ^3.0.0 - '@nomicfoundation/hardhat-ignition@0.15.13': - resolution: {integrity: sha512-G4XGPWvxs9DJhZ6PE1wdvKjHkjErWbsETf4c7YxO6GUz+MJGlw+PtgbnCwhL3tQzSq3oD4MB0LGi+sK0polpUA==} + '@nomicfoundation/hardhat-ignition-viem@3.0.2': + resolution: {integrity: sha512-SbKUzPPIqDIkZyqCIKeEomoRJHmjyJR4QCVGXfQLV2XsPsMnXlT92i/KfQSRB8TrxXoDnobRFynUKRPLgNalUA==} peerDependencies: - '@nomicfoundation/hardhat-verify': ^2.1.0 - hardhat: ^2.26.0 + '@nomicfoundation/hardhat-ignition': ^3.0.2 + '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/hardhat-viem': ^3.0.0 + '@nomicfoundation/ignition-core': ^3.0.2 + hardhat: ^3.0.0 + viem: 2.30.6 - '@nomicfoundation/hardhat-network-helpers@1.1.0': - resolution: {integrity: sha512-ZS+NulZuR99NUHt2VwcgZvgeD6Y63qrbORNRuKO+lTowJxNVsrJ0zbRx1j5De6G3dOno5pVGvuYSq2QVG0qCYg==} + '@nomicfoundation/hardhat-ignition@3.0.2': + resolution: {integrity: sha512-7OcSzZf9bZUt2At6oJizjFF0lMQWaI5En0akTHOp3crkVB2cVmnqZwCn+NGm7gdB8lzWPCXA/MWrm06eFM2G1w==} peerDependencies: - hardhat: ^2.26.0 + '@nomicfoundation/hardhat-verify': ^3.0.0 + hardhat: ^3.0.0 - '@nomicfoundation/hardhat-toolbox@4.0.0': - resolution: {integrity: sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA==} + '@nomicfoundation/hardhat-keystore@3.0.1': + resolution: {integrity: sha512-IHjTWf88Kp6ZsnwngVYNJphWwwhnkSjg+wBd9im5yo8IbvCjd0Otyv2ucw0Dol+mxM3t/6XJhEnhbA3JGe/EdQ==} peerDependencies: - '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 - '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-network-helpers': ^1.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 - '@typechain/ethers-v6': ^0.5.0 - '@typechain/hardhat': ^9.0.0 - '@types/chai': ^4.2.0 - '@types/mocha': '>=9.1.0' - '@types/node': 22.7.5 - chai: ^4.2.0 - ethers: ^6.4.0 - hardhat: ^2.11.0 - hardhat-gas-reporter: ^1.0.8 - solidity-coverage: ^0.8.1 - ts-node: '>=8.0.0' - typechain: ^8.3.0 - typescript: 5.8.3 + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-mocha@3.0.1': + resolution: {integrity: sha512-qkQoKniAPQ4P8mbdW6kw4XKU1CyMdlgAjyKL4n3C7Me8CwtZzpQ2YSMsDlqAbl+t61r+f0+7G1dC34bn/hjaoA==} + + '@nomicfoundation/hardhat-network-helpers@3.0.0': + resolution: {integrity: sha512-Nemas5cEaHyb4QoK40+USMxHMhIr4csRhpJFzm1T9I0/Wd1szw9kG412ubjUJxgm82ofyJGH3i5NKu7QgprmVg==} + peerDependencies: + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-node-test-reporter@3.0.1': + resolution: {integrity: sha512-p6yNKZFnJ2OMplXx7zi45KGWr4hr/qMkg+gTuSSLLlph7NL1DGjGG+N6GrZs46AGSrsnYEocKXGnavl92dxEig==} + + '@nomicfoundation/hardhat-node-test-runner@3.0.2': + resolution: {integrity: sha512-1cCJ/R5kMCja0tqdjFbeoLJugUNxGKATDq14KILYj0FjDZsJr3Kh1P3HiikTNSgG+pK5H2t2llVQ8ycWMXncFg==} + peerDependencies: + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-toolbox-mocha-ethers@3.0.0': + resolution: {integrity: sha512-2WiLWh701im222k/rdSPaQSQzR5RdrpaIVbsGt9z42zqZoEmehoYidUcVrIWG1ocAvfHS9LuxHo6nBd0xMHRnQ==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^4.0.0 + '@nomicfoundation/hardhat-ethers-chai-matchers': ^3.0.0 + '@nomicfoundation/hardhat-ignition': ^3.0.0 + '@nomicfoundation/hardhat-ignition-ethers': ^3.0.0 + '@nomicfoundation/hardhat-keystore': ^3.0.0 + '@nomicfoundation/hardhat-mocha': ^3.0.0 + '@nomicfoundation/hardhat-network-helpers': ^3.0.0 + '@nomicfoundation/hardhat-typechain': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/ignition-core': ^3.0.0 + chai: ^5.1.2 + ethers: ^6.14.0 + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-toolbox-viem@5.0.0': + resolution: {integrity: sha512-pls++zTi+NcYPV6lWpyEFJqblfvaQ9oMXDOFfob1u1GT3PilXOcl3pRC9gHOCPnujOrU8xdiWfuZ/4X/26Ve5A==} + peerDependencies: + '@nomicfoundation/hardhat-ignition': ^3.0.0 + '@nomicfoundation/hardhat-ignition-viem': ^3.0.0 + '@nomicfoundation/hardhat-keystore': ^3.0.0 + '@nomicfoundation/hardhat-network-helpers': ^3.0.0 + '@nomicfoundation/hardhat-node-test-runner': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/hardhat-viem': ^3.0.0 + '@nomicfoundation/hardhat-viem-assertions': ^3.0.0 + '@nomicfoundation/ignition-core': ^3.0.0 + hardhat: ^3.0.0 + viem: 2.30.6 '@nomicfoundation/hardhat-toolbox@5.0.0': resolution: {integrity: sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==} @@ -2850,16 +2896,44 @@ packages: typechain: ^8.3.0 typescript: 5.8.3 - '@nomicfoundation/hardhat-verify@2.1.1': - resolution: {integrity: sha512-K1plXIS42xSHDJZRkrE2TZikqxp9T4y6jUMUNI/imLgN5uCcEQokmfU0DlyP9zzHncYK92HlT5IWP35UVCLrPw==} + '@nomicfoundation/hardhat-typechain@3.0.0': + resolution: {integrity: sha512-wwPNrb+a/IrvMpj94VsXyKM64T0SJFXsmmqCHnGfh/iAdZmX5J9ILBLeDUE9JW5rL6ove8TB7OcXZkGp8unB4w==} peerDependencies: - hardhat: ^2.26.0 + '@nomicfoundation/hardhat-ethers': ^4.0.0 + ethers: ^6.14.0 + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-utils@3.0.0': + resolution: {integrity: sha512-dpzumbxM69ny/BSVd/8jquZO3wjg61e+S81DJPJwQ7naeZNai1r9gYuxT65VgKKTYZG/xKwrP36tJvB+gRtBrg==} + + '@nomicfoundation/hardhat-verify@3.0.1': + resolution: {integrity: sha512-gFLN8CekE0TvkwyjQ3eChoeZHd2gi4gVp+a6ntOZtlAUUbvxuKIq5OanzBa1SOPtwnYXsBAPKDsiC5uOVW4crw==} + peerDependencies: + hardhat: ^3.0.0 + + '@nomicfoundation/hardhat-viem-assertions@3.0.1': + resolution: {integrity: sha512-WkMngGc585JVujTfFvCp9Z+BGB2HlgZKNfGDDHAffTs7uZvW8IXsT8PtoKLsggbdNUFbLhaJEP833UAVbruZVg==} + peerDependencies: + '@nomicfoundation/hardhat-viem': ^3.0.0 + hardhat: ^3.0.0 + viem: 2.30.6 + + '@nomicfoundation/hardhat-viem@3.0.0': + resolution: {integrity: sha512-4QHBfTgJuo1O8vK9AO2AQYKsIp9yg06aF9C+WydDr2XS7VLJYh3g3gZdszLbSD9eHWsuviN688VKbcmfIZNWvQ==} + peerDependencies: + hardhat: ^3.0.0 + viem: 2.30.6 + + '@nomicfoundation/hardhat-zod-utils@3.0.0': + resolution: {integrity: sha512-xAi+45+V82pZZ9QGDEiii0wp+SXXH/8hS7/pk7S0gOG6h29gPuE42yek8wh3Ff0M+DrsB/RKZjcezmdwH5a6mQ==} + peerDependencies: + zod: ^3.23.8 - '@nomicfoundation/ignition-core@0.15.13': - resolution: {integrity: sha512-Z4T1WIbw0EqdsN9RxtnHeQXBi7P/piAmCu8bZmReIdDo/2h06qgKWxjDoNfc9VBFZJ0+Dx79tkgQR3ewxMDcpA==} + '@nomicfoundation/ignition-core@3.0.2': + resolution: {integrity: sha512-Uwjgsc6RLp8Dfp5hJ8KHccfYyTpSdhn3uaYHzjSX83l/9JphZ4gyzZOYvnJk3wbXpOPjdCRQAHNkk20vv5Z/Jw==} - '@nomicfoundation/ignition-ui@0.15.12': - resolution: {integrity: sha512-nQl8tusvmt1ANoyIj5RQl9tVSEmG0FnNbtwnWbTim+F8JLm4YLHWS0yEgYUZC+BEO3oS0D8r6V8a02JGZJgqiQ==} + '@nomicfoundation/ignition-ui@3.0.2': + resolution: {integrity: sha512-UdRhkcLIaAYIMCv9qS6vgVNOmJjdC5cKJAQ6+gAuiNL0VNBPKyyJ8vdIJx66EwAznj6a/IvNyvncB0/ZfqGU1A==} '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': resolution: {integrity: sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==} @@ -3181,33 +3255,9 @@ packages: '@semaphore-protocol/utils@4.9.1': resolution: {integrity: sha512-fhiVW/CL+zU/DvKAibBh3thEg2GKTMvNEl2V+fcJYbiyjxjZPfwvVHS/tP2wxBibU8bvtfcuqAk3WFdJXYFG2A==} - '@sentry/core@5.30.0': - resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} - engines: {node: '>=6'} - - '@sentry/hub@5.30.0': - resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} - engines: {node: '>=6'} - - '@sentry/minimal@5.30.0': - resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} - engines: {node: '>=6'} - - '@sentry/node@5.30.0': - resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} - engines: {node: '>=6'} - - '@sentry/tracing@5.30.0': - resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} - engines: {node: '>=6'} - - '@sentry/types@5.30.0': - resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} - engines: {node: '>=6'} - - '@sentry/utils@5.30.0': - resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} - engines: {node: '>=6'} + '@sentry/core@9.46.0': + resolution: {integrity: sha512-it7JMFqxVproAgEtbLgCVBYtQ9fIb+Bu0JD+cEplTN/Ukpe6GaolyYib5geZqslVxhp2sQgT+58aGvfd/k0N8Q==} + engines: {node: '>=18'} '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -3234,6 +3284,12 @@ packages: '@solidity-parser/parser@0.20.2': resolution: {integrity: sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==} + '@streamparser/json-node@0.0.22': + resolution: {integrity: sha512-sJT2ptNRwqB1lIsQrQlCoWk5rF4tif9wDh+7yluAGijJamAhrHGYpFB/Zg3hJeceoZypi74ftXk8DHzwYpbZSg==} + + '@streamparser/json@0.0.22': + resolution: {integrity: sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -3523,15 +3579,15 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - '@types/bn.js@5.2.0': - resolution: {integrity: sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==} - '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} '@types/chai-as-promised@7.1.8': resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + '@types/chai-as-promised@8.0.2': + resolution: {integrity: sha512-meQ1wDr1K5KRCSvG2lX7n7/5wf70BeptTKst0axGvnN6zqaVpRqegoIbugiAPSqOW9K9aL8gDVrm7a2LXOtn2Q==} + '@types/chai@4.3.20': resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} @@ -3629,9 +3685,6 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pbkdf2@3.1.2': - resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} - '@types/prettier@2.7.3': resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} @@ -3658,9 +3711,6 @@ packages: '@types/resolve@0.0.8': resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} - '@types/secp256k1@4.0.6': - resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} - '@types/send@0.17.5': resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} @@ -4007,14 +4057,6 @@ packages: aes-js@4.0.0-beta.5: resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -4055,9 +4097,6 @@ packages: resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} engines: {node: '>=0.4.2'} - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -4251,9 +4290,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base-x@3.0.11: - resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} - base-x@4.0.1: resolution: {integrity: sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==} @@ -4305,9 +4341,6 @@ packages: blake2b-wasm@2.4.0: resolution: {integrity: sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==} - blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - bluebird@3.4.7: resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} @@ -4333,10 +4366,6 @@ packages: bowser@2.12.1: resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} - boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} - brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -4384,18 +4413,12 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - bs58@5.0.0: resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==} bs58@6.0.0: resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} - bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} - buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -4486,13 +4509,9 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} - - cbor@9.0.2: - resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} - engines: {node: '>=16'} + cbor2@1.12.0: + resolution: {integrity: sha512-3Cco8XQhi27DogSp9Ri6LYNZLi/TBY/JVnDe+mj06NkBjW/ZYOtekaEU4wZ4xcRMNrFkDv8KNtOAqHyDfz3lYg==} + engines: {node: '>=18.7'} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -4502,6 +4521,11 @@ packages: peerDependencies: chai: '>= 2.1.2 < 6' + chai-as-promised@8.0.2: + resolution: {integrity: sha512-1GadL+sEJVLzDjcawPM4kjfnL+p/9vrxiEUonowKOAzvVg0PixJUdtuDzdkDeQhK3zfOE76GqGkZIQ7/Adcrqw==} + peerDependencies: + chai: '>= 2.1.2 < 7' + chai@4.5.0: resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} @@ -4581,9 +4605,6 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -4611,14 +4632,6 @@ packages: '@types/snarkjs': ^0.7.x snarkjs: ^0.7.x - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -4709,9 +4722,6 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - command-line-args@5.2.1: resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} engines: {node: '>=4.0.0'} @@ -4819,10 +4829,6 @@ packages: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} - cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - cookie@0.7.2: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} @@ -5227,6 +5233,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} @@ -5549,19 +5559,12 @@ packages: ethereum-bloom-filters@1.2.0: resolution: {integrity: sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==} - ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} - ethereum-cryptography@1.2.0: resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} ethereum-cryptography@2.2.1: resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} - ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} - ethers@5.8.0: resolution: {integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==} @@ -5654,6 +5657,10 @@ packages: fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + fast-equals@5.2.2: + resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} + engines: {node: '>=6.0.0'} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -5793,6 +5800,10 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/1eea5bae12ae557d589f9f0f0edae2faa47cb262: + resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/1eea5bae12ae557d589f9f0f0edae2faa47cb262} + version: 1.9.4 + form-data-encoder@2.1.4: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} @@ -5813,9 +5824,6 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - fp-ts@1.19.3: - resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -6055,17 +6063,9 @@ packages: peerDependencies: hardhat: ^2.16.0 - hardhat@2.26.3: - resolution: {integrity: sha512-gBfjbxCCEaRgMCRgTpjo1CEoJwqNPhyGMMVHYZJxoQ3LLftp2erSVf8ZF6hTQC0r2wst4NcqNmLWqMnHg1quTw==} + hardhat@3.0.4: + resolution: {integrity: sha512-6BoteHrD8nq5/yCUJGfYmspTulkjQZgRJOBPwXNZLz3fJV8B2wYLnDSbkKpyI97yhAmfzuc2qp6yBHPK5Msl4A==} hasBin: true - peerDependencies: - ts-node: '*' - typescript: 5.8.3 - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true has-flag@1.0.0: resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} @@ -6221,10 +6221,6 @@ packages: https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - human-id@4.1.1: resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} hasBin: true @@ -6242,10 +6238,6 @@ packages: engines: {node: '>=18'} hasBin: true - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -6269,9 +6261,6 @@ packages: immer@10.0.2: resolution: {integrity: sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==} - immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -6288,10 +6277,6 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -6322,9 +6307,6 @@ packages: intersection-observer@0.12.2: resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} - io-ts@1.10.4: - resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} - ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -6512,6 +6494,14 @@ packages: javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jiti@1.21.7: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true @@ -6716,9 +6706,6 @@ packages: lodash.castarray@4.4.0: resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} - lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -6798,9 +6785,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lru_map@0.3.3: - resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - magic-string@0.30.18: resolution: {integrity: sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==} @@ -6925,10 +6909,6 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - merge-descriptors@2.0.0: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} @@ -7223,14 +7203,16 @@ packages: mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} - mnemonist@0.38.5: - resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} - mocha@10.8.2: resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} engines: {node: '>= 14.0.0'} hasBin: true + mocha@11.7.2: + resolution: {integrity: sha512-lkqVJPmqqG/w5jmmFtiRvtA2jkDyNVUcefFJKb2uyX4dekk8Okgqop3cgbFiaIvj8uCRJVTP5x9dfxGyXm2jvQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -7338,9 +7320,6 @@ packages: node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - node-emoji@1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} @@ -7370,10 +7349,6 @@ packages: resolution: {integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==} engines: {node: '>=10'} - nofilter@3.1.0: - resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} - engines: {node: '>=12.19'} - non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} @@ -7439,9 +7414,6 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - obliterator@2.0.5: - resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==} - ofetch@1.4.1: resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} @@ -7481,10 +7453,6 @@ packages: os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -7540,9 +7508,9 @@ packages: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + engines: {node: '>=18'} p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} @@ -8030,10 +7998,6 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - raw-body@3.0.0: resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} engines: {node: '>= 0.8'} @@ -8256,12 +8220,13 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + resolve@1.1.7: resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} - resolve@1.17.0: - resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} - resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -8279,6 +8244,9 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -8299,10 +8267,6 @@ packages: ripemd160@2.0.2: resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true - robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -8358,18 +8322,10 @@ packages: scrypt-js@3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - secp256k1@4.0.4: - resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} - engines: {node: '>=18.0.0'} - section-matter@1.0.0: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -8516,11 +8472,6 @@ packages: solady@0.1.4: resolution: {integrity: sha512-BQKpX9Ezdp6WpUcT3H7cWdZKH31Ih7yZiUOQ6SUYzJ6gYjCB0KXPg77bS+pzmeQEtdMNK56gjlaqtn6ptFPSXQ==} - solc@0.8.26: - resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} - engines: {node: '>=10.0.0'} - hasBin: true - solhint-plugin-prettier@0.1.0: resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} peerDependencies: @@ -8548,9 +8499,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map@0.2.0: resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} engines: {node: '>=0.8.0'} @@ -8598,10 +8546,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - stacktrace-parser@0.1.11: - resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} - engines: {node: '>=6'} - static-eval@2.0.2: resolution: {integrity: sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==} @@ -8879,10 +8823,6 @@ packages: tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - tmp@0.2.5: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} @@ -8991,9 +8931,6 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsort@0.0.1: - resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - tsup@8.5.0: resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} engines: {node: '>=18'} @@ -9021,6 +8958,10 @@ packages: tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} engines: {node: '>= 0.8.0'} @@ -9041,10 +8982,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} @@ -9106,6 +9043,10 @@ packages: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} + undici@6.21.3: + resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} + engines: {node: '>=18.17'} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -9586,10 +9527,6 @@ packages: engines: {node: '>=8'} hasBin: true - widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -9604,6 +9541,9 @@ packages: workerpool@6.5.1: resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} + workerpool@9.3.3: + resolution: {integrity: sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -9824,6 +9764,22 @@ packages: snapshots: + '@actions/core@1.11.1': + dependencies: + '@actions/exec': 1.1.1 + '@actions/http-client': 2.2.3 + + '@actions/exec@1.1.1': + dependencies: + '@actions/io': 1.1.3 + + '@actions/http-client@2.2.3': + dependencies: + tunnel: 0.0.6 + undici: 5.29.0 + + '@actions/io@1.1.3': {} + '@adraffy/ens-normalize@1.10.1': {} '@adraffy/ens-normalize@1.11.0': {} @@ -9839,7 +9795,7 @@ snapshots: dependencies: comlink: 4.4.2 commander: 12.1.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) fflate: 0.8.2 pako: 2.1.0 tslib: 2.8.1 @@ -9850,7 +9806,7 @@ snapshots: dependencies: comlink: 4.4.2 commander: 12.1.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) fflate: 0.8.2 pako: 2.1.0 tslib: 2.8.1 @@ -9875,10 +9831,10 @@ snapshots: '@babel/helpers': 7.28.3 '@babel/parser': 7.28.3 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) '@babel/types': 7.28.2 convert-source-map: 2.0.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -9919,7 +9875,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -9936,7 +9892,7 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -9959,14 +9915,7 @@ snapshots: '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-imports@7.27.1': - dependencies: - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -9981,9 +9930,9 @@ snapshots: '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -9998,7 +9947,7 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.28.3 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10007,13 +9956,13 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -10031,7 +9980,7 @@ snapshots: '@babel/helper-wrap-function@7.28.3': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -10049,7 +9998,7 @@ snapshots: dependencies: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10076,7 +10025,7 @@ snapshots: dependencies: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10120,14 +10069,14 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.3) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: @@ -10167,7 +10116,7 @@ snapshots: '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10181,7 +10130,7 @@ snapshots: dependencies: '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10238,7 +10187,7 @@ snapshots: '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10284,7 +10233,7 @@ snapshots: '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10324,7 +10273,7 @@ snapshots: '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.3) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -10407,7 +10356,7 @@ snapshots: dependencies: '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) '@babel/types': 7.28.2 @@ -10622,24 +10571,12 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.28.3 '@babel/types': 7.28.2 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/traverse@7.28.3': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.3 - '@babel/template': 7.27.2 - '@babel/types': 7.28.2 - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - '@babel/traverse@7.28.3(supports-color@5.5.0)': + '@babel/traverse@7.28.3(supports-color@5.5.0)': dependencies: '@babel/code-frame': 7.27.1 '@babel/generator': 7.28.3 @@ -10912,7 +10849,7 @@ snapshots: '@emotion/babel-plugin@11.13.5': dependencies: - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/runtime': 7.28.3 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 @@ -11042,7 +10979,7 @@ snapshots: '@noir-lang/noir_js': 1.0.0-beta.3 comlink: 4.4.2 viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) - vite-plugin-top-level-await: 1.6.0(vite@6.3.5(@types/node@22.7.5)(jiti@1.21.7)(tsx@4.20.5)(yaml@2.8.1)) + vite-plugin-top-level-await: 1.6.0(rollup@4.49.0)(vite@6.3.5(@types/node@22.7.5)(jiti@1.21.7)(tsx@4.20.5)(yaml@2.8.1)) vite-plugin-wasm: 3.5.0(vite@6.3.5(@types/node@22.7.5)(jiti@1.21.7)(tsx@4.20.5)(yaml@2.8.1)) vitest: 1.6.1(@types/node@22.7.5) web-worker: 1.5.0 @@ -11297,7 +11234,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -11317,8 +11254,6 @@ snapshots: '@ethereumjs/rlp@4.0.1': {} - '@ethereumjs/rlp@5.0.2': {} - '@ethereumjs/tx@4.2.0': dependencies: '@ethereumjs/common': 3.2.0 @@ -11332,11 +11267,6 @@ snapshots: ethereum-cryptography: 2.2.1 micro-ftch: 0.3.1 - '@ethereumjs/util@9.1.0': - dependencies: - '@ethereumjs/rlp': 5.0.2 - ethereum-cryptography: 2.2.1 - '@ethersproject/abi@5.8.0': dependencies: '@ethersproject/address': 5.8.0 @@ -11668,7 +11598,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -11992,7 +11922,7 @@ snapshots: bufferutil: 4.0.9 cross-fetch: 4.1.0 date-fns: 2.30.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) eciesjs: 0.4.15 eventemitter2: 6.4.9 readable-stream: 3.6.2 @@ -12016,7 +11946,7 @@ snapshots: '@paulmillr/qr': 0.2.1 bowser: 2.12.1 cross-fetch: 4.1.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) eciesjs: 0.4.15 eth-rpc-errors: 4.0.3 eventemitter2: 6.4.9 @@ -12042,7 +11972,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) lodash.memoize: 4.1.2 pony-cause: 2.1.11 semver: 7.7.2 @@ -12054,7 +11984,7 @@ snapshots: dependencies: '@ethereumjs/tx': 4.2.0 '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) semver: 7.7.2 superstruct: 1.0.4 transitivePeerDependencies: @@ -12067,7 +11997,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) pony-cause: 2.1.11 semver: 7.7.2 uuid: 9.0.1 @@ -12081,7 +12011,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) pony-cause: 2.1.11 semver: 7.7.2 uuid: 9.0.1 @@ -12329,83 +12259,150 @@ snapshots: '@noir-lang/types@1.0.0-beta.3': {} - '@nomicfoundation/edr-darwin-arm64@0.11.3': {} + '@nomicfoundation/edr-darwin-arm64@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-darwin-x64@0.11.3': {} + '@nomicfoundation/edr-darwin-x64@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-linux-arm64-gnu@0.11.3': {} + '@nomicfoundation/edr-linux-arm64-gnu@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-linux-arm64-musl@0.11.3': {} + '@nomicfoundation/edr-linux-arm64-musl@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-linux-x64-gnu@0.11.3': {} + '@nomicfoundation/edr-linux-x64-gnu@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-linux-x64-musl@0.11.3': {} + '@nomicfoundation/edr-linux-x64-musl@0.12.0-next.5': + optional: true - '@nomicfoundation/edr-win32-x64-msvc@0.11.3': {} + '@nomicfoundation/edr-win32-x64-msvc@0.12.0-next.5': + optional: true - '@nomicfoundation/edr@0.11.3': - dependencies: - '@nomicfoundation/edr-darwin-arm64': 0.11.3 - '@nomicfoundation/edr-darwin-x64': 0.11.3 - '@nomicfoundation/edr-linux-arm64-gnu': 0.11.3 - '@nomicfoundation/edr-linux-arm64-musl': 0.11.3 - '@nomicfoundation/edr-linux-x64-gnu': 0.11.3 - '@nomicfoundation/edr-linux-x64-musl': 0.11.3 - '@nomicfoundation/edr-win32-x64-msvc': 0.11.3 + '@nomicfoundation/edr@0.12.0-next.5': + optionalDependencies: + '@nomicfoundation/edr-darwin-arm64': 0.12.0-next.5 + '@nomicfoundation/edr-darwin-x64': 0.12.0-next.5 + '@nomicfoundation/edr-linux-arm64-gnu': 0.12.0-next.5 + '@nomicfoundation/edr-linux-arm64-musl': 0.12.0-next.5 + '@nomicfoundation/edr-linux-x64-gnu': 0.12.0-next.5 + '@nomicfoundation/edr-linux-x64-musl': 0.12.0-next.5 + '@nomicfoundation/edr-win32-x64-msvc': 0.12.0-next.5 - '@nomicfoundation/hardhat-chai-matchers@2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-chai-matchers@2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@types/chai-as-promised': 7.1.8 - chai: 4.5.0 - chai-as-promised: 7.1.2(chai@4.5.0) + chai: 5.3.3 + chai-as-promised: 7.1.2(chai@5.3.3) deep-eql: 4.1.4 ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) ordinal: 1.0.3 - '@nomicfoundation/hardhat-chai-matchers@2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-errors@3.0.1': dependencies: - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@types/chai-as-promised': 7.1.8 + '@nomicfoundation/hardhat-utils': 3.0.0 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-utils': 3.0.0 + '@types/chai-as-promised': 8.0.2 + chai: 4.5.0 + chai-as-promised: 8.0.2(chai@4.5.0) + deep-eql: 5.0.2 + ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-utils': 3.0.0 + '@types/chai-as-promised': 8.0.2 chai: 5.3.3 - chai-as-promised: 7.1.2(chai@5.3.3) - deep-eql: 4.1.4 + chai-as-promised: 8.0.2(chai@5.3.3) + deep-eql: 5.0.2 ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - ordinal: 1.0.3 + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - supports-color - '@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - '@nomicfoundation/hardhat-foundry@1.2.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': dependencies: - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - picocolors: 1.1.1 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + debug: 4.4.1(supports-color@5.5.0) + ethereum-cryptography: 2.2.1 + ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@nomicfoundation/hardhat-ignition-ethers@3.0.2(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - supports-color - '@nomicfoundation/hardhat-ignition-ethers@0.15.14(fcdc0daa2d57f78852817b38ea974238)': + '@nomicfoundation/hardhat-ignition-ethers@3.0.2(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ignition': 0.15.13(@nomicfoundation/hardhat-verify@2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - '@nomicfoundation/ignition-core': 0.15.13(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - supports-color - '@nomicfoundation/hardhat-ignition@0.15.13(@nomicfoundation/hardhat-verify@2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': + '@nomicfoundation/hardhat-ignition-viem@3.0.2(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-viem@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: - '@nomicfoundation/hardhat-verify': 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/ignition-core': 0.15.13(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@nomicfoundation/ignition-ui': 0.15.12 - chalk: 4.1.2 - debug: 4.4.1(supports-color@8.1.1) - fs-extra: 10.1.0 - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-viem': 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@nomicfoundation/ignition-ui': 3.0.2 + chalk: 5.3.0 + debug: 4.4.1(supports-color@5.5.0) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) json5: 2.2.3 prompts: 2.4.2 transitivePeerDependencies: @@ -12413,104 +12410,213 @@ snapshots: - supports-color - utf-8-validate - '@nomicfoundation/hardhat-network-helpers@1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-keystore@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - ethereumjs-util: 7.1.5 - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + '@noble/ciphers': 1.2.1 + '@noble/hashes': 1.7.1 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) + chalk: 5.3.0 + debug: 4.4.1(supports-color@5.5.0) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + zod: 3.25.76 + transitivePeerDependencies: + - supports-color - '@nomicfoundation/hardhat-toolbox@4.0.0(4308261da56a39dba1593c5e7639385e)': + '@nomicfoundation/hardhat-mocha@3.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-network-helpers': 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-verify': 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@typechain/ethers-v6': 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) - '@types/chai': 4.3.20 - '@types/mocha': 10.0.10 - '@types/node': 22.7.5 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + mocha: 11.7.2 + tsx: 4.20.5 + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@nomicfoundation/hardhat-network-helpers@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-node-test-reporter@3.0.1': + dependencies: + '@actions/core': 1.11.1 + chalk: 5.3.0 + jest-diff: 29.7.0 + + '@nomicfoundation/hardhat-node-test-runner@3.0.2(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-node-test-reporter': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + tsx: 4.20.5 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-toolbox-mocha-ethers@3.0.0(6b85ed473db2330ad75256729be2beb8)': + dependencies: + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ethers-chai-matchers': 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition-ethers': 3.0.2(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-keystore': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-mocha': 3.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-network-helpers': 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-typechain': 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + chai: 5.3.3 + ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@nomicfoundation/hardhat-toolbox-mocha-ethers@3.0.0(90f84ad61b06116a79b8c39a263ea2f9)': + dependencies: + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ethers-chai-matchers': 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition-ethers': 3.0.2(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-keystore': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-mocha': 3.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-network-helpers': 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-typechain': 3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) chai: 4.5.0 ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-gas-reporter: 2.3.0(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(utf-8-validate@5.0.10) - solidity-coverage: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - ts-node: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) - typechain: 8.3.2(typescript@5.8.3) - typescript: 5.8.3 + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@nomicfoundation/hardhat-toolbox-viem@5.0.0(57ef2920aa19fe9eb07b2e80a48eb774)': + dependencies: + '@nomicfoundation/hardhat-ignition': 3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-ignition-viem': 3.0.2(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-viem@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@nomicfoundation/hardhat-keystore': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-node-test-runner': 3.0.2(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-viem': 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@nomicfoundation/hardhat-viem-assertions': 3.0.1(@nomicfoundation/hardhat-viem@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@nomicfoundation/ignition-core': 3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@nomicfoundation/hardhat-toolbox@4.0.0(954e9d9570193eb16113ebf9d0b86657)': + '@nomicfoundation/hardhat-toolbox@5.0.0(a2c664a2c86c3ae5dd9cd312b280c590)': dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@4.5.0)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-network-helpers': 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-verify': 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-chai-matchers': 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition-ethers': 3.0.2(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-ignition@3.0.2(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-verify': 3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@typechain/ethers-v6': 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) '@types/chai': 4.3.20 '@types/mocha': 10.0.10 '@types/node': 22.7.5 - chai: 4.5.0 + chai: 5.3.3 ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-gas-reporter: 1.0.10(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - solidity-coverage: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat-gas-reporter: 1.0.10(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + solidity-coverage: 0.8.16(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ts-node: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) typechain: 8.3.2(typescript@5.8.3) typescript: 5.8.3 - '@nomicfoundation/hardhat-toolbox@5.0.0(199633c01e7f1dcb215c469e4940f39b)': + '@nomicfoundation/hardhat-typechain@3.0.0(@nomicfoundation/hardhat-ethers@4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3)': dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.1.0(@nomicfoundation/hardhat-ethers@3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.3.3)(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ignition-ethers': 0.15.14(fcdc0daa2d57f78852817b38ea974238) - '@nomicfoundation/hardhat-network-helpers': 1.1.0(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-verify': 2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-ethers': 4.0.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) '@typechain/ethers-v6': 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) - '@types/chai': 4.3.20 - '@types/mocha': 10.0.10 - '@types/node': 22.7.5 - chai: 5.3.3 + debug: 4.4.1(supports-color@5.5.0) ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-gas-reporter: 1.0.10(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - solidity-coverage: 0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - ts-node: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) typechain: 8.3.2(typescript@5.8.3) - typescript: 5.8.3 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + - typescript - '@nomicfoundation/hardhat-verify@2.1.1(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-utils@3.0.0': + dependencies: + '@streamparser/json-node': 0.0.22 + debug: 4.4.1(supports-color@5.5.0) + env-paths: 2.2.1 + ethereum-cryptography: 2.2.1 + fast-equals: 5.2.2 + json-stream-stringify: 3.1.6 + rfdc: 1.4.1 + undici: 6.21.3 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-verify@3.0.1(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.8.0 - '@ethersproject/address': 5.8.0 - cbor: 8.1.0 - debug: 4.4.1(supports-color@8.1.1) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - lodash.clonedeep: 4.5.0 - picocolors: 1.1.1 - semver: 6.3.1 - table: 6.9.0 - undici: 5.29.0 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) + cbor2: 1.12.0 + chalk: 5.3.0 + debug: 4.4.1(supports-color@5.5.0) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + semver: 7.7.2 + zod: 3.25.76 transitivePeerDependencies: - supports-color - '@nomicfoundation/ignition-core@0.15.13(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@nomicfoundation/hardhat-viem-assertions@3.0.1(@nomicfoundation/hardhat-viem@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-viem': 3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-viem@3.0.0(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-zod-utils@3.0.0(zod@3.25.76)': + dependencies: + '@nomicfoundation/hardhat-utils': 3.0.0 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/ignition-core@3.0.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: '@ethersproject/address': 5.6.1 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 '@nomicfoundation/solidity-analyzer': 0.1.2 - cbor: 9.0.2 - debug: 4.4.1(supports-color@8.1.1) + cbor2: 1.12.0 + debug: 4.4.1(supports-color@5.5.0) ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - fs-extra: 10.1.0 immer: 10.0.2 - lodash: 4.17.21 + lodash-es: 4.17.21 ndjson: 2.0.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@nomicfoundation/ignition-ui@0.15.12': {} + '@nomicfoundation/ignition-ui@3.0.2': {} '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': optional: true @@ -13069,54 +13175,7 @@ snapshots: - bufferutil - utf-8-validate - '@sentry/core@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/hub@5.30.0': - dependencies: - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/minimal@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/types': 5.30.0 - tslib: 1.14.1 - - '@sentry/node@5.30.0': - dependencies: - '@sentry/core': 5.30.0 - '@sentry/hub': 5.30.0 - '@sentry/tracing': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - cookie: 0.4.2 - https-proxy-agent: 5.0.1 - lru_map: 0.3.3 - tslib: 1.14.1 - transitivePeerDependencies: - - supports-color - - '@sentry/tracing@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/types@5.30.0': {} - - '@sentry/utils@5.30.0': - dependencies: - '@sentry/types': 5.30.0 - tslib: 1.14.1 + '@sentry/core@9.46.0': {} '@sideway/address@4.1.5': dependencies: @@ -13138,6 +13197,12 @@ snapshots: '@solidity-parser/parser@0.20.2': {} + '@streamparser/json-node@0.0.22': + dependencies: + '@streamparser/json': 0.0.22 + + '@streamparser/json@0.0.22': {} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -13505,12 +13570,12 @@ snapshots: typechain: 8.3.2(typescript@5.8.3) typescript: 5.8.3 - '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))': + '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))': dependencies: '@typechain/ethers-v6': 0.5.1(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) ethers: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) fs-extra: 9.1.0 - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) typechain: 8.3.2(typescript@5.8.3) '@types/acorn@4.0.6': @@ -13540,10 +13605,6 @@ snapshots: dependencies: '@babel/types': 7.28.2 - '@types/bn.js@5.2.0': - dependencies: - '@types/node': 22.7.5 - '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 @@ -13553,6 +13614,10 @@ snapshots: dependencies: '@types/chai': 4.3.20 + '@types/chai-as-promised@8.0.2': + dependencies: + '@types/chai': 4.3.20 + '@types/chai@4.3.20': {} '@types/concat-stream@1.6.1': @@ -13662,10 +13727,6 @@ snapshots: '@types/parse-json@4.0.2': {} - '@types/pbkdf2@3.1.2': - dependencies: - '@types/node': 22.7.5 - '@types/prettier@2.7.3': {} '@types/prop-types@15.7.15': {} @@ -13691,10 +13752,6 @@ snapshots: dependencies: '@types/node': 22.7.5 - '@types/secp256k1@4.0.6': - dependencies: - '@types/node': 22.7.5 - '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 @@ -13748,7 +13805,7 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) eslint: 8.57.1 optionalDependencies: typescript: 5.8.3 @@ -13764,7 +13821,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3) '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) eslint: 8.57.1 ts-api-utils: 1.4.3(typescript@5.8.3) optionalDependencies: @@ -13778,7 +13835,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -14602,17 +14659,6 @@ snapshots: aes-js@4.0.0-beta.5: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - ajv-draft-04@1.0.0(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -14658,10 +14704,6 @@ snapshots: amdefine@1.0.1: optional: true - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - ansi-colors@4.1.3: {} ansi-escapes@4.3.2: @@ -14859,10 +14901,6 @@ snapshots: balanced-match@1.0.2: {} - base-x@3.0.11: - dependencies: - safe-buffer: 5.2.1 - base-x@4.0.1: {} base-x@5.0.1: {} @@ -14922,8 +14960,6 @@ snapshots: b4a: 1.6.7 nanoassert: 2.0.0 - blakejs@1.2.1: {} - bluebird@3.4.7: {} bluebird@3.7.2: {} @@ -14938,7 +14974,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 @@ -14952,17 +14988,6 @@ snapshots: bowser@2.12.1: {} - boxen@5.1.2: - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -15038,10 +15063,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.3) - bs58@4.0.1: - dependencies: - base-x: 3.0.11 - bs58@5.0.0: dependencies: base-x: 4.0.1 @@ -15050,12 +15071,6 @@ snapshots: dependencies: base-x: 5.0.1 - bs58check@2.1.2: - dependencies: - bs58: 4.0.1 - create-hash: 1.2.0 - safe-buffer: 5.2.1 - buffer-from@1.1.2: {} buffer-indexof-polyfill@1.0.2: {} @@ -15136,25 +15151,24 @@ snapshots: caseless@0.12.0: {} - cbor@8.1.0: - dependencies: - nofilter: 3.1.0 - - cbor@9.0.2: - dependencies: - nofilter: 3.1.0 + cbor2@1.12.0: {} ccount@2.0.1: {} - chai-as-promised@7.1.2(chai@4.5.0): + chai-as-promised@7.1.2(chai@5.3.3): + dependencies: + chai: 5.3.3 + check-error: 1.0.3 + + chai-as-promised@8.0.2(chai@4.5.0): dependencies: chai: 4.5.0 - check-error: 1.0.3 + check-error: 2.1.1 - chai-as-promised@7.1.2(chai@5.3.3): + chai-as-promised@8.0.2(chai@5.3.3): dependencies: chai: 5.3.3 - check-error: 1.0.3 + check-error: 2.1.1 chai@4.5.0: dependencies: @@ -15243,8 +15257,6 @@ snapshots: chownr@2.0.0: {} - ci-info@2.0.0: {} - ci-info@3.9.0: {} cipher-base@1.0.6: @@ -15279,10 +15291,6 @@ snapshots: loglevel: 1.9.2 snarkjs: 0.7.4 - clean-stack@2.2.0: {} - - cli-boxes@2.2.1: {} - cli-cursor@3.1.0: dependencies: restore-cursor: 3.1.0 @@ -15375,8 +15383,6 @@ snapshots: comma-separated-tokens@2.0.3: {} - command-exists@1.2.9: {} - command-line-args@5.2.1: dependencies: array-back: 3.1.0 @@ -15478,8 +15484,6 @@ snapshots: cookie-signature@1.2.2: {} - cookie@0.4.2: {} - cookie@0.7.2: {} core-js-compat@3.45.1: @@ -15919,6 +15923,8 @@ snapshots: diff@5.2.0: {} + diff@7.0.0: {} + diffie-hellman@5.0.3: dependencies: bn.js: 4.12.2 @@ -16219,7 +16225,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -16365,24 +16371,6 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 - ethereum-cryptography@0.1.3: - dependencies: - '@types/pbkdf2': 3.1.2 - '@types/secp256k1': 4.0.6 - blakejs: 1.2.1 - browserify-aes: 1.2.0 - bs58check: 2.1.2 - create-hash: 1.2.0 - create-hmac: 1.1.7 - hash.js: 1.1.7 - keccak: 3.0.4 - pbkdf2: 3.1.3 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - scrypt-js: 3.0.1 - secp256k1: 4.0.4 - setimmediate: 1.0.5 - ethereum-cryptography@1.2.0: dependencies: '@noble/hashes': 1.2.0 @@ -16397,14 +16385,6 @@ snapshots: '@scure/bip32': 1.4.0 '@scure/bip39': 1.3.0 - ethereumjs-util@7.1.5: - dependencies: - '@types/bn.js': 5.2.0 - bn.js: 5.2.2 - create-hash: 1.2.0 - ethereum-cryptography: 0.1.3 - rlp: 2.2.7 - ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@ethersproject/abi': 5.8.0 @@ -16540,7 +16520,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -16590,6 +16570,8 @@ snapshots: fast-diff@1.3.0: {} + fast-equals@5.2.2: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -16666,7 +16648,7 @@ snapshots: finalhandler@2.1.0: dependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -16725,7 +16707,7 @@ snapshots: follow-redirects@1.15.11(debug@4.4.1): optionalDependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) for-each@0.3.5: dependencies: @@ -16736,6 +16718,8 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/1eea5bae12ae557d589f9f0f0edae2faa47cb262: {} + form-data-encoder@2.1.4: {} form-data@2.5.5: @@ -16759,8 +16743,6 @@ snapshots: forwarded@0.2.0: {} - fp-ts@1.19.3: {} - fraction.js@4.3.7: {} framer-motion@6.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -17077,7 +17059,7 @@ snapshots: axios: 0.21.4(debug@4.4.1) chalk: 4.1.2 chokidar: 3.6.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) enquirer: 2.4.1 ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) form-data: 4.0.4 @@ -17091,11 +17073,11 @@ snapshots: - supports-color - utf-8-validate - hardhat-gas-reporter@1.0.10(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10): + hardhat-gas-reporter@1.0.10(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10): dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' @@ -17103,7 +17085,7 @@ snapshots: - debug - utf-8-validate - hardhat-gas-reporter@2.3.0(bufferutil@4.0.9)(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(utf-8-validate@5.0.10): + hardhat-gas-reporter@2.3.0(bufferutil@4.0.9)(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76): dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 @@ -17115,12 +17097,12 @@ snapshots: cli-table3: 0.6.5 ethereum-cryptography: 2.2.1 glob: 10.4.5 - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) jsonschema: 1.5.0 lodash: 4.17.21 markdown-table: 2.0.0 sha1: 1.1.1 - viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + viem: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - bufferutil - debug @@ -17128,50 +17110,26 @@ snapshots: - utf-8-validate - zod - hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10): + hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: - '@ethereumjs/util': 9.1.0 - '@ethersproject/abi': 5.8.0 - '@nomicfoundation/edr': 0.11.3 + '@nomicfoundation/edr': 0.12.0-next.5 + '@nomicfoundation/hardhat-errors': 3.0.1 + '@nomicfoundation/hardhat-utils': 3.0.0 + '@nomicfoundation/hardhat-zod-utils': 3.0.0(zod@3.25.76) '@nomicfoundation/solidity-analyzer': 0.1.2 - '@sentry/node': 5.30.0 + '@sentry/core': 9.46.0 adm-zip: 0.4.16 - aggregate-error: 3.1.0 - ansi-escapes: 4.3.2 - boxen: 5.1.2 - chokidar: 4.0.3 - ci-info: 2.0.0 - debug: 4.4.1(supports-color@8.1.1) + chalk: 5.3.0 + debug: 4.4.1(supports-color@5.5.0) enquirer: 2.4.1 - env-paths: 2.2.1 - ethereum-cryptography: 1.2.0 - find-up: 5.0.0 - fp-ts: 1.19.3 - fs-extra: 7.0.1 - immutable: 4.3.7 - io-ts: 1.10.4 - json-stream-stringify: 3.1.6 - keccak: 3.0.4 - lodash: 4.17.21 + ethereum-cryptography: 2.2.1 micro-eth-signer: 0.14.0 - mnemonist: 0.38.5 - mocha: 10.8.2 - p-map: 4.0.0 - picocolors: 1.1.1 - raw-body: 2.5.2 - resolve: 1.17.0 - semver: 6.3.1 - solc: 0.8.26(debug@4.4.1) - source-map-support: 0.5.21 - stacktrace-parser: 0.1.11 - tinyglobby: 0.2.14 - tsort: 0.0.1 - undici: 5.29.0 - uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) - optionalDependencies: - ts-node: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3) - typescript: 5.8.3 + p-map: 7.0.3 + resolve.exports: 2.0.3 + semver: 7.7.2 + tsx: 4.20.5 + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + zod: 3.25.76 transitivePeerDependencies: - bufferutil - supports-color @@ -17425,13 +17383,6 @@ snapshots: https-browserify@1.0.0: {} - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - human-id@4.1.1: {} human-signals@4.3.1: {} @@ -17440,10 +17391,6 @@ snapshots: husky@9.1.7: {} - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -17460,8 +17407,6 @@ snapshots: immer@10.0.2: {} - immutable@4.3.7: {} - import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -17473,8 +17418,6 @@ snapshots: imurmurhash@0.1.4: {} - indent-string@4.0.0: {} - inflight@1.0.6: dependencies: once: 1.4.0 @@ -17496,10 +17439,6 @@ snapshots: intersection-observer@0.12.2: {} - io-ts@1.10.4: - dependencies: - fp-ts: 1.19.3 - ipaddr.js@1.9.1: {} iron-webcrypto@1.2.1: {} @@ -17652,6 +17591,15 @@ snapshots: javascript-natural-sort@0.7.1: {} + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-get-type@29.6.3: {} + jiti@1.21.7: {} jju@1.4.0: {} @@ -17836,8 +17784,6 @@ snapshots: lodash.castarray@4.4.0: {} - lodash.clonedeep@4.5.0: {} - lodash.debounce@4.0.8: {} lodash.get@4.4.2: {} @@ -17905,8 +17851,6 @@ snapshots: dependencies: yallist: 4.0.0 - lru_map@0.3.3: {} - magic-string@0.30.18: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -18195,8 +18139,6 @@ snapshots: media-typer@1.1.0: {} - memorystream@0.3.1: {} - merge-descriptors@2.0.0: {} merge-stream@2.0.0: {} @@ -18606,7 +18548,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) decode-named-character-reference: 1.2.0 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -18628,7 +18570,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -18729,10 +18671,6 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.1 - mnemonist@0.38.5: - dependencies: - obliterator: 2.0.5 - mocha@10.8.2: dependencies: ansi-colors: 4.1.3 @@ -18756,6 +18694,29 @@ snapshots: yargs-parser: 20.2.9 yargs-unparser: 2.0.0 + mocha@11.7.2: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.4.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 9.0.5 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.3 + yargs: 17.7.2 + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + mri@1.2.0: {} ms@2.1.3: {} @@ -18906,8 +18867,6 @@ snapshots: node-addon-api@2.0.2: {} - node-addon-api@5.1.0: {} - node-emoji@1.11.0: dependencies: lodash: 4.17.21 @@ -18954,8 +18913,6 @@ snapshots: util: 0.12.5 vm-browserify: 1.1.2 - nofilter@3.1.0: {} - non-layered-tidy-tree-layout@2.0.2: {} nopt@3.0.6: @@ -19015,8 +18972,6 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - obliterator@2.0.5: {} - ofetch@1.4.1: dependencies: destr: 2.0.5 @@ -19075,8 +19030,6 @@ snapshots: os-browserify@0.3.0: {} - os-tmpdir@1.0.2: {} - outdent@0.5.0: {} ox@0.6.9(typescript@5.8.3)(zod@3.25.76): @@ -19093,21 +19046,6 @@ snapshots: transitivePeerDependencies: - zod - ox@0.7.1(typescript@5.8.3): - dependencies: - '@adraffy/ens-normalize': 1.11.0 - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.0.9(typescript@5.8.3)(zod@3.25.76) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - zod - ox@0.7.1(typescript@5.8.3)(zod@3.22.4): dependencies: '@adraffy/ens-normalize': 1.11.0 @@ -19168,9 +19106,7 @@ snapshots: p-map@2.1.0: {} - p-map@4.0.0: - dependencies: - aggregate-error: 3.1.0 + p-map@7.0.3: {} p-try@2.2.0: {} @@ -19593,13 +19529,6 @@ snapshots: range-parser@1.2.1: {} - raw-body@2.5.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - raw-body@3.0.0: dependencies: bytes: 3.1.2 @@ -19880,11 +19809,9 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.1.7: {} + resolve.exports@2.0.3: {} - resolve@1.17.0: - dependencies: - path-parse: 1.0.7 + resolve@1.1.7: {} resolve@1.22.10: dependencies: @@ -19903,6 +19830,8 @@ snapshots: reusify@1.1.0: {} + rfdc@1.4.1: {} + rimraf@2.7.1: dependencies: glob: 7.2.3 @@ -19925,10 +19854,6 @@ snapshots: hash-base: 3.1.0 inherits: 2.0.4 - rlp@2.2.7: - dependencies: - bn.js: 5.2.2 - robust-predicates@3.0.2: {} rollup@4.49.0: @@ -19959,7 +19884,7 @@ snapshots: router@2.2.0: dependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -20022,19 +19947,11 @@ snapshots: scrypt-js@3.0.1: {} - secp256k1@4.0.4: - dependencies: - elliptic: 6.6.1 - node-addon-api: 5.1.0 - node-gyp-build: 4.8.4 - section-matter@1.0.0: dependencies: extend-shallow: 2.0.1 kind-of: 6.0.3 - semver@5.7.2: {} - semver@6.3.1: {} semver@7.5.4: @@ -20045,7 +19962,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -20257,18 +20174,6 @@ snapshots: solady@0.1.4: {} - solc@0.8.26(debug@4.4.1): - dependencies: - command-exists: 1.2.9 - commander: 8.3.0 - follow-redirects: 1.15.11(debug@4.4.1) - js-sha3: 0.8.0 - memorystream: 0.3.1 - semver: 5.7.2 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.4.3(prettier@3.6.2))(prettier@3.6.2): dependencies: '@prettier/sync': 0.3.0(prettier@3.6.2) @@ -20304,7 +20209,7 @@ snapshots: transitivePeerDependencies: - typescript - solidity-coverage@0.8.16(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)): + solidity-coverage@0.8.16(hardhat@3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: '@ethersproject/abi': 5.8.0 '@solidity-parser/parser': 0.20.2 @@ -20315,7 +20220,7 @@ snapshots: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.13.5)(@types/node@22.7.5)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat: 3.0.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) jsonschema: 1.5.0 lodash: 4.17.21 mocha: 10.8.2 @@ -20337,11 +20242,6 @@ snapshots: source-map-js@1.2.1: {} - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - source-map@0.2.0: dependencies: amdefine: 1.0.1 @@ -20378,10 +20278,6 @@ snapshots: stackback@0.0.2: {} - stacktrace-parser@0.1.11: - dependencies: - type-fest: 0.7.1 - static-eval@2.0.2: dependencies: escodegen: 1.14.3 @@ -20708,10 +20604,6 @@ snapshots: dependencies: tmp: 0.2.5 - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - tmp@0.2.5: {} to-buffer@1.2.1: @@ -20812,15 +20704,13 @@ snapshots: tslib@2.8.1: {} - tsort@0.0.1: {} - tsup@8.5.0(@microsoft/api-extractor@7.52.11(@types/node@22.7.5))(@swc/core@1.13.5)(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.8.3)(yaml@2.8.1): dependencies: bundle-require: 5.1.0(esbuild@0.25.9) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) esbuild: 0.25.9 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 @@ -20853,6 +20743,8 @@ snapshots: tty-browserify@0.0.1: {} + tunnel@0.0.6: {} + type-check@0.3.2: dependencies: prelude-ls: 1.1.2 @@ -20867,8 +20759,6 @@ snapshots: type-fest@0.21.3: {} - type-fest@0.7.1: {} - type-fest@1.4.0: {} type-is@2.0.1: @@ -20880,7 +20770,7 @@ snapshots: typechain@8.3.2(typescript@5.8.3): dependencies: '@types/prettier': 2.7.3 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) fs-extra: 7.0.1 glob: 7.1.7 js-sha3: 0.8.0 @@ -20928,6 +20818,8 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 + undici@6.21.3: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: @@ -21179,23 +21071,6 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10): - dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.25.76) - isows: 1.0.7(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - ox: 0.7.1(typescript@5.8.3) - ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - viem@2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4): dependencies: '@noble/curves': 1.9.1 @@ -21233,7 +21108,7 @@ snapshots: vite-node@1.6.1(@types/node@22.7.5): dependencies: cac: 6.7.14 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) pathe: 1.1.2 picocolors: 1.1.1 vite: 5.4.19(@types/node@22.7.5) @@ -21255,7 +21130,7 @@ snapshots: '@volar/typescript': 2.4.23 '@vue/language-core': 2.2.0(typescript@5.8.3) compare-versions: 6.1.1 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) kolorist: 1.8.0 local-pkg: 1.1.2 magic-string: 0.30.18 @@ -21297,17 +21172,6 @@ snapshots: - '@swc/helpers' - rollup - vite-plugin-top-level-await@1.6.0(vite@6.3.5(@types/node@22.7.5)(jiti@1.21.7)(tsx@4.20.5)(yaml@2.8.1)): - dependencies: - '@rollup/plugin-virtual': 3.0.2(rollup@4.49.0) - '@swc/core': 1.13.5 - '@swc/wasm': 1.13.5 - uuid: 10.0.0 - vite: 6.3.5(@types/node@22.7.5)(jiti@1.21.7)(tsx@4.20.5)(yaml@2.8.1) - transitivePeerDependencies: - - '@swc/helpers' - - rollup - vite-plugin-wasm@3.5.0(vite@5.4.19(@types/node@22.7.5)): dependencies: vite: 5.4.19(@types/node@22.7.5) @@ -21318,7 +21182,7 @@ snapshots: vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@5.4.19(@types/node@22.7.5)): dependencies: - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.8.3) optionalDependencies: @@ -21360,7 +21224,7 @@ snapshots: '@vitest/utils': 1.6.1 acorn-walk: 8.3.4 chai: 4.5.0 - debug: 4.4.1(supports-color@8.1.1) + debug: 4.4.1(supports-color@5.5.0) execa: 8.0.1 local-pkg: 0.5.1 magic-string: 0.30.18 @@ -21521,10 +21385,6 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - widest-line@3.1.0: - dependencies: - string-width: 4.2.3 - word-wrap@1.2.5: {} wordwrap@1.0.0: {} @@ -21536,6 +21396,8 @@ snapshots: workerpool@6.5.1: {} + workerpool@9.3.3: {} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 diff --git a/templates/default/.gitignore b/templates/default/.gitignore index 10f4ccffc4..4704916269 100644 --- a/templates/default/.gitignore +++ b/templates/default/.gitignore @@ -7,8 +7,7 @@ node_modules /artifacts # TypeChain files -/typechain -/typechain-types +/types # solidity-coverage files /coverage diff --git a/templates/default/contracts/Mocks/MockRISC0Verifier.sol b/templates/default/contracts/Mocks/MockRISC0Verifier.sol index 9d0b7d8416..3656241ae3 100644 --- a/templates/default/contracts/Mocks/MockRISC0Verifier.sol +++ b/templates/default/contracts/Mocks/MockRISC0Verifier.sol @@ -5,7 +5,7 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity ^0.8.27; -import {IRiscZeroVerifier, Receipt} from "@risc0/ethereum/contracts/src/IRiscZeroVerifier.sol"; +import {IRiscZeroVerifier, Receipt} from "@risc0/ethereum/contracts/IRiscZeroVerifier.sol"; contract MockRISC0Verifier is IRiscZeroVerifier { function verify( diff --git a/templates/default/contracts/MyProgram.sol b/templates/default/contracts/MyProgram.sol index abef1bf734..14f461a926 100755 --- a/templates/default/contracts/MyProgram.sol +++ b/templates/default/contracts/MyProgram.sol @@ -5,7 +5,7 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.27; -import {IRiscZeroVerifier} from "@risc0/ethereum/contracts/src/IRiscZeroVerifier.sol"; +import {IRiscZeroVerifier} from "@risc0/ethereum/contracts/IRiscZeroVerifier.sol"; import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol"; import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; import {IEnclave} from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol"; diff --git a/templates/default/deploy/default.ts b/templates/default/deploy/default.ts index e43f4abd17..9f4d3a603b 100644 --- a/templates/default/deploy/default.ts +++ b/templates/default/deploy/default.ts @@ -4,60 +4,60 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployer } = await hre.getNamedAccounts(); - const { deploy } = hre.deployments; - - const [deployerAccount] = await hre.ethers.getSigners(); - const enclave = await hre.deployments.get("Enclave"); - - const verifier = await deploy("MockRISC0Verifier", { - from: deployer, - args: [], - log: true, - }); - - const imageId = await deploy("ImageID", { - from: deployer, - args: [], - log: true, - }); - const imageIdContract = await hre.ethers.getContractAt( - "ImageID", - imageId.address, - ); - const programId = await imageIdContract.PROGRAM_ID(); - - const inputValidator = await deploy("InputValidator", { - from: deployer, - args: [], - log: true, - }); - - const e3Program = await deploy("MyProgram", { - from: deployer, - args: [enclave.address, verifier.address, programId, inputValidator.address], - log: true, - }); - - const enclaveContract = new hre.ethers.Contract( - enclave.address, - enclave.abi, - deployerAccount, - ); - const result = enclaveContract.interface.encodeFunctionData( - "enableE3Program", - [e3Program.address], - ); - const tx = await deployerAccount.sendTransaction({ - to: enclave.address, - data: result, - }); +import { readDeploymentArgs, storeDeploymentArgs } from "@enclave-e3/contracts/scripts/utils.js"; +import { Enclave__factory as EnclaveFactory } from "@enclave-e3/contracts/types"; +import hre from "hardhat"; + +export const deployTemplate = async () => { + const { ethers } = await hre.network.connect(); + const [owner] = await ethers.getSigners(); + + const chain = hre.globalOptions.network; + + const enclaveAddress = readDeploymentArgs("Enclave", chain)?.address; + if (!enclaveAddress) { + throw new Error("Enclave address not found, it must be deployed first"); + } + const enclave = EnclaveFactory.connect(enclaveAddress, owner); + const verifier = await ethers.deployContract("MockRISC0Verifier"); + await verifier.waitForDeployment(); + + storeDeploymentArgs({ + address: await verifier.getAddress(), + }, "MockRISC0Verifier", chain); + + const imageId = await ethers.deployContract("ImageID"); + await imageId.waitForDeployment(); + + storeDeploymentArgs({ + address: await imageId.getAddress(), + }, "ImageID", chain); + + const programId = await imageId.PROGRAM_ID(); + + const inputValidator = await ethers.deployContract("InputValidator"); + await inputValidator.waitForDeployment(); + + storeDeploymentArgs({ + address: await inputValidator.getAddress(), + }, "InputValidator", chain); + + const e3Program = await ethers.deployContract("MyProgram", [await enclave.getAddress(), await verifier.getAddress(), programId, await inputValidator.getAddress()]); + await e3Program.waitForDeployment(); + + storeDeploymentArgs({ + address: await e3Program.getAddress(), + constructorArgs: { + enclave: await enclave.getAddress(), + verifier: await verifier.getAddress(), + programId, + inputValidator: await inputValidator.getAddress(), + }, + }, "MyProgram", chain); + + const tx = await enclave.enableE3Program(await e3Program.getAddress()); + await tx.wait(); + + console.log("E3 Program enabled for Enclave's template"); }; -export default func; -func.tags = ["default"]; -func.dependencies = ["enclave"]; diff --git a/templates/default/deploy/enclave.ts b/templates/default/deploy/enclave.ts deleted file mode 100644 index 51969b5393..0000000000 --- a/templates/default/deploy/enclave.ts +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. - -import deployEnclave from "@enclave-e3/contracts/deploy/enclave"; -import deployMocks from "@enclave-e3/contracts/deploy/mocks"; -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - await deployEnclave(hre); - // INFO: We need to deploy the mock contract due to the decryptionVerifier. - // Once we have a real verifier, we can remove this. - await deployMocks(hre); -}; - -export default func; -func.tags = ["enclave", "mocks"]; diff --git a/templates/default/deployed_contracts.json b/templates/default/deployed_contracts.json new file mode 100644 index 0000000000..463baed55c --- /dev/null +++ b/templates/default/deployed_contracts.json @@ -0,0 +1,67 @@ +{ + "localhost": { + "Enclave": { + "constructorArgs": { + "params": "0x000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000fc00100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000003fffffff000001", + "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "maxDuration": "2592000", + "registry": "0x0000000000000000000000000000000000000001" + }, + "blockNumber": 2, + "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" + }, + "CiphernodeRegistry": { + "constructorArgs": { + "enclaveAddress": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "blockNumber": 4, + "address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" + }, + "NaiveRegistryFilter": { + "constructorArgs": { + "ciphernodeRegistryAddress": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", + "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "blockNumber": 5, + "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" + }, + "MockComputeProvider": { + "blockNumber": 7, + "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F" + }, + "MockDecryptionVerifier": { + "blockNumber": 8, + "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" + }, + "MockInputValidator": { + "blockNumber": 9, + "address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" + }, + "MockE3Program": { + "constructorArgs": { + "mockInputValidator": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" + }, + "blockNumber": 10, + "address": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" + }, + "MockRISC0Verifier": { + "address": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" + }, + "ImageID": { + "address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82" + }, + "InputValidator": { + "address": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "MyProgram": { + "address": "0x0B306BF915C4d645ff596e518fAf3F9669b97016", + "constructorArgs": { + "enclave": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "verifier": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "programId": "0xaf928ebf39fec4696c3f41f473a1a9473b67d723c6373149c6ab99ba4c1a76ef", + "inputValidator": "0x9A676e781A523b5d0C0e43731313A708CB607508" + } + } + } +} \ No newline at end of file diff --git a/templates/default/enclave.config.yaml b/templates/default/enclave.config.yaml index 729e7543d6..20a95d91b4 100644 --- a/templates/default/enclave.config.yaml +++ b/templates/default/enclave.config.yaml @@ -2,8 +2,8 @@ chains: - name: "hardhat" rpc_url: "ws://localhost:8545" contracts: - e3_program: "0x9A676e781A523b5d0C0e43731313A708CB607508" - enclave: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + e3_program: "0x0B306BF915C4d645ff596e518fAf3F9669b97016" + enclave: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" ciphernode_registry: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" filter_registry: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" diff --git a/templates/default/hardhat.config.ts b/templates/default/hardhat.config.ts index cbff13d0e6..47eefe39e4 100644 --- a/templates/default/hardhat.config.ts +++ b/templates/default/hardhat.config.ts @@ -4,62 +4,153 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -import "@nomicfoundation/hardhat-toolbox"; -import "hardhat-deploy"; -import "@enclave-e3/contracts/deploy/enclave"; -import { task } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; +import { ciphernodeAdd } from "@enclave-e3/contracts/tasks/ciphernode"; +import { cleanDeploymentsTask } from "@enclave-e3/contracts/tasks/utils"; + +import hardhatEthersChaiMatchers from "@nomicfoundation/hardhat-ethers-chai-matchers"; +import hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers"; +import hardhatNetworkHelpers from "@nomicfoundation/hardhat-network-helpers"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import hardhatTypechainPlugin from "@nomicfoundation/hardhat-typechain"; + import type { HardhatUserConfig } from "hardhat/config"; +import { configVariable } from "hardhat/config"; +import { ConfigurationVariable } from "hardhat/types/config"; + +const mnemonic = configVariable("MNEMONIC"); +const privateKey = configVariable("PRIVATE_KEY"); +const infuraApiKey = configVariable("INFURA_API_KEY"); + +const chainIds = { + "arbitrum-mainnet": 42161, + avalanche: 43114, + bsc: 56, + ganache: 1337, + hardhat: 31337, + mainnet: 1, + "optimism-mainnet": 10, + "polygon-mainnet": 137, + "polygon-mumbai": 80001, + sepolia: 11155111, + goerli: 5, +}; + +function getChainConfig(chain: keyof typeof chainIds, apiUrl: string) { + let jsonRpcUrl: string; + switch (chain) { + case "avalanche": + jsonRpcUrl = "https://api.avax.network/ext/bc/C/rpc"; + break; + case "bsc": + jsonRpcUrl = "https://bsc-dataseed1.binance.org"; + break; + default: + jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; + } -task("ciphernode:add", "Register a ciphernode to the registry") - .addParam("ciphernodeAddress", "address of ciphernode to register") - .setAction(async function (taskArguments: TaskArguments, hre) { - const registry = await hre.deployments.get("CiphernodeRegistryOwnable"); - const [deployer] = await hre.ethers.getSigners(); - const registryContract = new hre.ethers.Contract( - registry.address, - registry.abi, - deployer, - ); - const result = registryContract.interface.encodeFunctionData( - "addCiphernode", - [taskArguments.ciphernodeAddress.replace(/"/g, "")], - ); - const tx = await deployer.sendTransaction({ - to: registryContract.target, - data: result, - }); - await tx.wait(); - console.log(`Ciphernode ${taskArguments.ciphernodeAddress} registered`); - }); + let accounts: + | [ConfigurationVariable] + | { count: number; mnemonic: ConfigurationVariable; path: string }; + if (privateKey) { + accounts = [privateKey]; + } else { + accounts = { + count: 10, + mnemonic: mnemonic, + path: "m/44'/60'/0'/0", + }; + } + + return { + accounts, + chainId: chainIds[chain], + url: jsonRpcUrl, + type: "http" as const, + chainType: "l1" as const, + blockExplorers: { + etherscan: { + apiUrl, + }, + }, + }; +} const config: HardhatUserConfig = { + tasks: [ + ciphernodeAdd, + cleanDeploymentsTask, + ], + plugins: [ + hardhatTypechainPlugin, + hardhatEthersChaiMatchers, + hardhatIgnitionEthers, + hardhatNetworkHelpers, + hardhatToolboxMochaEthersPlugin, + ], + typechain: { + outDir: "./types", + tsNocheck: false, + }, + networks: { + hardhat: { + type: "edr-simulated", + chainType: "l1", + }, + ganache: { + accounts: { + mnemonic, + }, + chainId: chainIds.ganache, + url: "http://localhost:8545", + type: "http", + }, + arbitrum: getChainConfig( + "arbitrum-mainnet", + process.env.ARBISCAN_API_KEY || "", + ), + avalanche: getChainConfig("avalanche", process.env.SNOWTRACE_API_KEY || ""), + bsc: getChainConfig("bsc", process.env.BSCSCAN_API_KEY || ""), + mainnet: getChainConfig("mainnet", process.env.ETHERSCAN_API_KEY || ""), + optimism: getChainConfig( + "optimism-mainnet", + process.env.OPTIMISM_API_KEY || "", + ), + "polygon-mainnet": getChainConfig( + "polygon-mainnet", + process.env.POLYGONSCAN_API_KEY || "", + ), + "polygon-mumbai": getChainConfig( + "polygon-mumbai", + process.env.POLYGONSCAN_API_KEY || "", + ), + sepolia: getChainConfig("sepolia", process.env.ETHERSCAN_API_KEY || ""), + goerli: getChainConfig("goerli", process.env.ETHERSCAN_API_KEY || ""), + }, solidity: { - version: "0.8.27", - overrides: { - "node_modules/poseidon-solidity/PoseidonT3.sol": { - version: "0.7.0", + npmFilesToBuild: [ + "poseidon-solidity/PoseidonT3.sol", + "@enclave-e3/contracts/contracts/Enclave.sol", + "@enclave-e3/contracts/contracts/registry/CiphernodeRegistryOwnable.sol", + "@enclave-e3/contracts/contracts/registry/NaiveRegistryFilter.sol", + "@enclave-e3/contracts/contracts/test/MockInputValidator.sol", + "@enclave-e3/contracts/contracts/test/MockCiphernodeRegistry.sol", + "@enclave-e3/contracts/contracts/test/MockComputeProvider.sol", + "@enclave-e3/contracts/contracts/test/MockDecryptionVerifier.sol", + "@enclave-e3/contracts/contracts/test/MockE3Program.sol", + "@enclave-e3/contracts/contracts/test/MockRegistryFilter.sol", + ], + compilers: [ + { + version: "0.8.27", settings: { optimizer: { enabled: true, - runs: 2 ** 32 - 1, + runs: 800, }, }, }, - }, - }, - external: { - contracts: [ - { - artifacts: "node_modules/@enclave-e3/contracts/artifacts", - }, ], }, - namedAccounts: { - deployer: { - default: 0, // Use the first account as deployer - }, - }, }; export default config; diff --git a/templates/default/package.json b/templates/default/package.json index 15794fb9da..858fbef7fa 100644 --- a/templates/default/package.json +++ b/templates/default/package.json @@ -2,10 +2,13 @@ "name": "enclave-example", "version": "0.0.0", "private": true, + "type": "module", "scripts": { "ciphernode:add": "hardhat run scripts/ciphernode-add.ts -- ", "compile": "hardhat compile", - "deploy": "hardhat run scripts/deploy-local.ts --network localhost", + "clean:ignition:deployments": "rm -rf ./ignition/deployments/chain-31337", + "clean:deployments": "hardhat utils:clean-deployments && pnpm clean:ignition:deployments", + "deploy": "pnpm clean:deployments && hardhat run scripts/deploy-local.ts --network localhost", "deploy:dev": "hardhat run scripts/deploy-local.ts", "dev:all": "./scripts/dev_all.sh", "dev:ciphernodes": "./scripts/dev_ciphernodes.sh", @@ -25,35 +28,34 @@ "yargs": "^18.0.0" }, "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.5", - "@nomicfoundation/hardhat-network-helpers": "^1.0.10", - "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.2", + "@nomicfoundation/hardhat-ethers": "4", + "@nomicfoundation/hardhat-ethers-chai-matchers": "^3.0.0", + "@nomicfoundation/hardhat-ignition": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^3.0.1", + "@nomicfoundation/hardhat-network-helpers": "3", + "@nomicfoundation/hardhat-toolbox-mocha-ethers": "3.0.0", + "@nomicfoundation/hardhat-typechain": "3", + "@nomicfoundation/hardhat-verify": "3", "@openzeppelin/contracts": "5.3.0", "@risc0/ethereum": "file:lib/risc0-ethereum", - "@typechain/ethers-v6": "^0.5.0", - "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.2.0", "@types/express": "^5.0.2", "@types/mocha": ">=9.1.0", - "@types/node": ">=18.0.0", + "@types/node": "22.7.5", "@zk-kit/lean-imt": "^2.1.0", "@zk-kit/lean-imt.sol": "2.0.0", "chai": "^4.2.0", "concurrently": "^9.1.2", "ethers": "^6.9.0", "express": "^5.1.0", - "hardhat": "^2.22.10", - "hardhat-deploy": "^0.12.1", - "hardhat-gas-reporter": "^1.0.8", + "hardhat": "^3.0.1", "poseidon-lite": "^0.3.0", "solidity-coverage": "^0.8.0", "ts-node": "^10.9.2", "tsx": "^4.20.3", - "typechain": "^8.3.0", "typed-rpc": "^6.1.1", "typescript": "^5.8.3", + "vitest": "^1.6.1", "wait-on": "^8.0.3" } } diff --git a/templates/default/scripts/deploy-local.ts b/templates/default/scripts/deploy-local.ts index 930935b479..7a7283e059 100644 --- a/templates/default/scripts/deploy-local.ts +++ b/templates/default/scripts/deploy-local.ts @@ -4,55 +4,31 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -// scripts/deploy-local.ts -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -// Import the deployment logic from your published package -// This assumes your package exports the deployment function -import deployEnclave from "@enclave-e3/contracts/deploy/enclave"; +import { deployEnclave } from "@enclave-e3/contracts/deploy/enclave"; +import { deployTemplate } from "../deploy/default"; async function main() { console.log("šŸš€ Deploying Enclave protocol locally..."); // Get hardhat runtime environment - const hre = require("hardhat"); + const hre = await import("hardhat"); + + const { ethers } = await hre.network.connect(); // Get deployer account - const [deployer] = await hre.ethers.getSigners(); + const [deployer] = await ethers.getSigners(); console.log("Deploying with account:", deployer.address); console.log( "Account balance:", - hre.ethers.formatEther( - await hre.ethers.provider.getBalance(deployer.address), + ethers.formatEther( + await ethers.provider.getBalance(deployer.address), ), ); - try { - // Execute the deployment - await deployEnclave(hre); - console.log("āœ… Enclave protocol deployed successfully!"); - - // Log deployed contract addresses - const enclave = await hre.deployments.get("Enclave"); - const registry = await hre.deployments.get("CiphernodeRegistryOwnable"); - const filter = await hre.deployments.get("NaiveRegistryFilter"); - - console.log("\nšŸ“‹ Deployed Contracts:"); - console.log("Enclave:", enclave.address); - console.log("CiphernodeRegistryOwnable:", registry.address); - console.log("NaiveRegistryFilter:", filter.address); - } catch (error) { - console.error("āŒ Deployment failed:", error); - process.exit(1); - } + // Execute the deployment + await deployEnclave(true); + await deployTemplate(); } // Execute the deployment -if (require.main === module) { - main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); -} +main().catch(console.error); diff --git a/templates/default/scripts/dev_ciphernodes.sh b/templates/default/scripts/dev_ciphernodes.sh index 8a088bb98f..cc08cbce9d 100755 --- a/templates/default/scripts/dev_ciphernodes.sh +++ b/templates/default/scripts/dev_ciphernodes.sh @@ -6,7 +6,7 @@ SIGNAL_FILE=/tmp/enclave_ciphernodes_ready cleanup() { echo "Cleaning up processes..." - enclave nodes down + pkill -9 -f "enclave start" sleep 2 pkill enclave echo "Cleanup complete" @@ -38,6 +38,7 @@ CN2=$(grep -A 1 'cn2:' enclave.config.yaml | grep 'address:' | sed 's/.*address: CN3=$(grep -A 1 'cn3:' enclave.config.yaml | grep 'address:' | sed 's/.*address: *"\([^"]*\)".*/\1/') # Add ciphernodes using variables from config.sh +pnpm run deploy && sleep 2 pnpm hardhat ciphernode:add --ciphernode-address $CN1 --network localhost pnpm hardhat ciphernode:add --ciphernode-address $CN2 --network localhost pnpm hardhat ciphernode:add --ciphernode-address $CN3 --network localhost diff --git a/templates/default/scripts/test_integration.sh b/templates/default/scripts/test_integration.sh index 442b43cbf2..e9f087cdac 100755 --- a/templates/default/scripts/test_integration.sh +++ b/templates/default/scripts/test_integration.sh @@ -25,7 +25,7 @@ export $(enclave print-env --chain hardhat) --prefix-colors "blue,cyan,magenta,yellow,green" \ --kill-others \ --success first \ - "wait-on http://localhost:13151/health && pnpm tsx ./tests/integration.spec.ts" \ + "wait-on http://localhost:13151/health && pnpm vitest run ./tests/integration.spec.ts" \ "pnpm dev:evm" \ "pnpm dev:ciphernodes" \ "TEST_MODE=1 pnpm dev:server" \ diff --git a/templates/default/server/index.ts b/templates/default/server/index.ts index b324ac0b26..1e3cef8282 100644 --- a/templates/default/server/index.ts +++ b/templates/default/server/index.ts @@ -149,7 +149,7 @@ async function handleE3ActivatedEvent(event: any) { console.log("šŸ“” Fetching E3 data from contract..."); const e3 = await sdk.getE3(e3Id); - console.log("āœ… Reveived E3 data from contract."); + console.log("āœ… Received E3 data from contract."); e3Sessions.set(sessionKey, { e3Id, diff --git a/templates/default/tests/integration.spec.ts b/templates/default/tests/integration.spec.ts index 325014d263..7da9ff660a 100644 --- a/templates/default/tests/integration.spec.ts +++ b/templates/default/tests/integration.spec.ts @@ -21,6 +21,8 @@ import { import { hexToBytes } from "viem"; import assert from "assert"; +import { describe, expect, it, beforeAll } from "vitest"; + export function getContractAddresses() { return { enclave: process.env.ENCLAVE_ADDRESS as `0x${string}`, @@ -30,6 +32,12 @@ export function getContractAddresses() { }; } +function hexToUint8Array(hexString: string) { + const hex = hexString.startsWith("0x") ? hexString.slice(2) : hexString; + const m = hex.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? []; + return new Uint8Array(m); +} + type E3Shared = { e3Id: bigint; e3Program: string; @@ -152,7 +160,7 @@ async function setupEventListeners( return { waitForEvent }; } -async function main() { +describe("Integration", () => { console.log("Testing..."); const contracts = getContractAddresses(); @@ -169,112 +177,90 @@ async function main() { "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", protocol: FheProtocol.BFV, }); - - const { waitForEvent } = await setupEventListeners(sdk, store); - - const threshold: [number, number] = [ - DEFAULT_E3_CONFIG.threshold_min, - DEFAULT_E3_CONFIG.threshold_max, - ]; - const startWindow = calculateStartWindow(60); - const duration = BigInt(10); - const e3ProgramParams = encodeBfvParams(); - const computeProviderParams = encodeComputeProviderParams( - DEFAULT_COMPUTE_PROVIDER_PARAMS - ); - - let state; - let event; - - // REQUEST phase - await waitForEvent(EnclaveEventType.E3_REQUESTED, async () => { - await sdk.requestE3({ - filter: contracts.filterRegistry, - threshold, - startWindow, - duration, - e3Program: contracts.e3Program, - e3ProgramParams, - computeProviderParams, - value: BigInt("1000000000000000"), // 0.001 ETH - }); - }); - - state = store.get(0n); - assert(state); - assert.strictEqual(state.e3Id, 0n); - assert.strictEqual(state.filter, contracts.filterRegistry); - assert.strictEqual(state.type, "requested"); - - // Ciphernodes will publish a public key within the COMMITTEE_PUBLISHED event - event = await waitForEvent(RegistryEventType.COMMITTEE_PUBLISHED); - - state = store.get(0n); - assert(state); - assert.strictEqual(state.type, "committee_published"); - assert.strictEqual(state.publicKey, event.data.publicKey); - - let { e3Id, publicKey } = state; - - // ACTIVATION phase - event = await waitForEvent(EnclaveEventType.E3_ACTIVATED, async () => { - await sdk.activateE3(e3Id, publicKey); - }); - - state = store.get(0n); - assert(state); - assert.strictEqual(state.type, "activated"); - - // INPUT PUBLISHING phase - const num1 = 12n; - const num2 = 21n; - const publicKeyBytes = hexToBytes(state.publicKey); - const enc1 = await sdk.encryptNumber(num1, publicKeyBytes); - const enc2 = await sdk.encryptNumber(num2, publicKeyBytes); - - await waitForEvent(EnclaveEventType.INPUT_PUBLISHED, async () => { - await sdk.publishInput( - e3Id, - `0x${Array.from(enc1, (b) => b.toString(16).padStart(2, "0")).join("")}` as `0x${string}`, + + it("should run an integration test", async () => { + const { waitForEvent } = await setupEventListeners(sdk, store); + + const threshold: [number, number] = [ + DEFAULT_E3_CONFIG.threshold_min, + DEFAULT_E3_CONFIG.threshold_max, + ]; + const startWindow = calculateStartWindow(60); + const duration = BigInt(10); + const e3ProgramParams = encodeBfvParams(); + const computeProviderParams = encodeComputeProviderParams( + DEFAULT_COMPUTE_PROVIDER_PARAMS ); - }); - await waitForEvent(EnclaveEventType.INPUT_PUBLISHED, async () => { - const hash2 = await sdk.publishInput( - e3Id, - `0x${Array.from(enc2, (b) => b.toString(16).padStart(2, "0")).join("")}` as `0x${string}`, + + let state; + let event; + + // REQUEST phase + await waitForEvent(EnclaveEventType.E3_REQUESTED, async () => { + console.log("Requested E3..."); + await sdk.requestE3({ + filter: contracts.filterRegistry, + threshold, + startWindow, + duration, + e3Program: contracts.e3Program, + e3ProgramParams, + computeProviderParams, + value: BigInt("1000000000000000"), // 0.001 ETH + }); + }); + + state = store.get(0n); + assert(state); + assert.strictEqual(state.e3Id, 0n); + assert.strictEqual(state.filter, contracts.filterRegistry); + assert.strictEqual(state.type, "requested"); + + // Ciphernodes will publish a public key within the COMMITTEE_PUBLISHED event + event = await waitForEvent(RegistryEventType.COMMITTEE_PUBLISHED); + + state = store.get(0n); + assert(state); + assert.strictEqual(state.type, "committee_published"); + assert.strictEqual(state.publicKey, event.data.publicKey); + + let { e3Id, publicKey } = state; + + // ACTIVATION phase + event = await waitForEvent(EnclaveEventType.E3_ACTIVATED, async () => { + await sdk.activateE3(e3Id, publicKey); + }); + + state = store.get(0n); + assert(state); + assert.strictEqual(state.type, "activated"); + + // INPUT PUBLISHING phase + const num1 = 12n; + const num2 = 21n; + const publicKeyBytes = hexToBytes(state.publicKey); + const enc1 = await sdk.encryptNumber(num1, publicKeyBytes); + const enc2 = await sdk.encryptNumber(num2, publicKeyBytes); + + await waitForEvent(EnclaveEventType.INPUT_PUBLISHED, async () => { + await sdk.publishInput( + e3Id, + `0x${Array.from(enc1, (b) => b.toString(16).padStart(2, "0")).join("")}` as `0x${string}`, + ); + }); + await waitForEvent(EnclaveEventType.INPUT_PUBLISHED, async () => { + await sdk.publishInput( + e3Id, + `0x${Array.from(enc2, (b) => b.toString(16).padStart(2, "0")).join("")}` as `0x${string}`, + ); + }); + + const plaintextEvent = await waitForEvent( + EnclaveEventType.PLAINTEXT_OUTPUT_PUBLISHED ); - }); - - const plaintextEvent = await waitForEvent( - EnclaveEventType.PLAINTEXT_OUTPUT_PUBLISHED - ); - - const parsed = hexToUint8Array(plaintextEvent.data.plaintextOutput); - - assert.strictEqual(BigInt(parsed[0]), num1 + num2); - - console.log(""); - console.log("*****************************************"); - console.log(" TEST WAS SUCCESSFUL!"); - console.log(" SHUTTING DOWN SERVICES"); - console.log("*****************************************"); - console.log(""); - - process.exit(0); -} - -main() - .then(() => console.log("Test successful")) - .catch((err) => { - console.log(""); - console.log(" āŒ Test failed "); - console.log(""); - console.log(err); - process.exit(1); - }); - -function hexToUint8Array(hexString: string) { - const hex = hexString.startsWith("0x") ? hexString.slice(2) : hexString; - const m = hex.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? []; - return new Uint8Array(m); -} + + const parsed = hexToUint8Array(plaintextEvent.data.plaintextOutput); + + expect(BigInt(parsed[0])).toBe(num1 + num2); + }, 9999999) +}) diff --git a/templates/default/tsconfig.json b/templates/default/tsconfig.json index b91e93146e..9d55246745 100644 --- a/templates/default/tsconfig.json +++ b/templates/default/tsconfig.json @@ -1,19 +1,25 @@ { "compilerOptions": { + "lib": ["es2023"], "target": "ES2022", - "module": "nodenext", - "esModuleInterop": true, - "moduleResolution": "nodenext", - "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "bundler", "strict": true, - "noEmit": true, + "esModuleInterop": true, "skipLibCheck": true, - "resolveJsonModule": true + "outDir": "dist", + "declaration": true, + "declarationMap": true }, "include": [ - "./tests/**/*", - "./deploy/**/*", - "./server/**/*", - "hardhat.config.ts" - ] + "hardhat.config.ts", + "scripts/**/*.ts", + "test/**/*.ts", + "tests/**/*.ts", + "types/**/*.ts", + "server/**/*.ts", + "deploy/**/*.ts", + "client/**/*.ts" + ], + "exclude": ["node_modules", "dist", "types"] } diff --git a/tests/integration/base.sh b/tests/integration/base.sh index 0fd5ac75f6..c112954358 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -16,6 +16,9 @@ until curl -f -s "http://localhost:8545" > /dev/null; do sleep 1 done +pnpm evm:clean +pnpm evm:deploy --network localhost + # set wallet to ag specifically enclave_wallet_set ag "$PRIVATE_KEY" diff --git a/tests/integration/enclave.config.yaml b/tests/integration/enclave.config.yaml index 321ed18c3a..69d5603303 100644 --- a/tests/integration/enclave.config.yaml +++ b/tests/integration/enclave.config.yaml @@ -2,7 +2,7 @@ chains: - name: "hardhat" rpc_url: "ws://localhost:8545" contracts: - enclave: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + enclave: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" ciphernode_registry: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" filter_registry: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index 0d6db3a54b..865bf7296a 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -21,10 +21,10 @@ CIPHERNODE_SECRET="We are the music makers and we are the dreamers of the dreams # These contracts are based on the deterministic order of hardhat deploy # We _may_ wish to get these off the hardhat environment somehow? -ENCLAVE_CONTRACT="0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" +ENCLAVE_CONTRACT="0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" REGISTRY_CONTRACT="0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" REGISTRY_FILTER_CONTRACT="0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" -INPUT_VALIDATOR_CONTRACT="0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" +INPUT_VALIDATOR_CONTRACT="0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" # These are random addresses for now CIPHERNODE_ADDRESS_1="0x2546BcD3c84621e976D8185a91A922aE77ECEc30" @@ -52,6 +52,8 @@ echo "Enclave binary: $ENCLAVE_BIN" cleanup() { echo "Cleaning up processes..." jobs -p | xargs -r kill -9 2>/dev/null || true + pkill -9 -f "target/debug/enclave" || true + pkill -9 -f "hardhat" || true exit ${1:-1} } @@ -172,7 +174,9 @@ kill_proc() { } kill_em_all() { + echo "Killing enclave" pkill -9 -f "target/debug/enclave" || true + pkill -9 -f "enclave start" || true pkill -9 -f "hardhat" || true } diff --git a/tests/integration/persist.sh b/tests/integration/persist.sh index 39e97b3f58..c29f6386c1 100755 --- a/tests/integration/persist.sh +++ b/tests/integration/persist.sh @@ -16,6 +16,9 @@ until curl -f -s "http://localhost:8545" > /dev/null; do sleep 1 done +pnpm evm:clean +pnpm evm:deploy --network localhost + # set wallet to ag specifically enclave_wallet_set ag "$PRIVATE_KEY"