From 71cf69e274a69c38365a8c41558febee67c028da Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 5 Jun 2024 09:51:40 +0200 Subject: [PATCH 1/2] Implement get_account_with_storage_recursive --- .../lib/src/account_with_storage_recursive.nr | 58 +++++++++++++++++++ ...account_with_storage_recursive_int_test.nr | 16 +++++ ethereum/circuits/lib/src/lib.nr | 2 + .../oracles/recursive/getStorageOracle.ts | 2 +- vlayer/ethereum/circuits/lib/src/token.nr | 4 +- .../circuits/is_dao_worthy/Verifier.toml | 2 +- 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 ethereum/circuits/lib/src/account_with_storage_recursive.nr create mode 100644 ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive.nr b/ethereum/circuits/lib/src/account_with_storage_recursive.nr new file mode 100644 index 000000000..11585de04 --- /dev/null +++ b/ethereum/circuits/lib/src/account_with_storage_recursive.nr @@ -0,0 +1,58 @@ +use crate::misc::{fragment::Fragment, types::{Address, Bytes32, ADDRESS_LENGTH, BYTES32_LENGTH}}; +use crate::serde::STORAGE_BLOCK_LEN; +use dep::std::verify_proof; +use crate::account_with_storage::StorageWithinBlock; +use dep::std::unsafe::zeroed; + +struct RecursiveProof { + key_hash: Field, + verification_key: [Field; 114], + proof: [Field; 93], +} + +global NUM_PUBLIC_INPUTS = 1 + 1 + ADDRESS_LENGTH + BYTES32_LENGTH + STORAGE_BLOCK_LEN; // chain_id + block_number + address + storage_key + public_return_inputs + +pub fn get_account_with_storage_recursive( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> StorageWithinBlock<1> { + let (storage_within_block, RecursiveProof {key_hash, verification_key, proof}) = get_account_with_storage_recursive_unconstrained(chain_id, block_number, address, storage_key); + + let mut public_inputs: Fragment = Fragment::empty(); + public_inputs.push_back(chain_id); + public_inputs.push_back(block_number as Field); + public_inputs.extend_back(address.serialize()); + public_inputs.extend_back(storage_key.serialize()); + public_inputs.extend_back(storage_within_block.serialize()); + let public_inputs_array: [Field; NUM_PUBLIC_INPUTS] = public_inputs.to_array(); + + verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs_array.as_slice(), + key_hash + ); + + storage_within_block +} + +#[oracle(get_account_with_storage_recursive)] +unconstrained fn get_account_with_storage_recursive_oracle( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> ([Field; STORAGE_BLOCK_LEN], RecursiveProof) {} + +unconstrained fn get_account_with_storage_recursive_unconstrained( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> (StorageWithinBlock<1>, RecursiveProof) { + let (return_value_serialized, proof) = get_account_with_storage_recursive_oracle(chain_id, block_number, address, storage_key); + let return_value = StorageWithinBlock::deserialize(return_value_serialized); + (return_value, proof) +} diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr new file mode 100644 index 000000000..fd7a5231d --- /dev/null +++ b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr @@ -0,0 +1,16 @@ +use crate::account_with_storage_recursive::{get_account_with_storage_recursive, RecursiveProof}; +use crate::account_with_storage::StorageWithinBlock; +use crate::fixtures::mainnet::paris::usdc_circle::{header::{number, hash}, account::{address, account} storage::{keys, values}}; +use crate::chain::ETHEREUM_MAINNET_ID; +use crate::misc::types::{Bytes32, Address}; +use dep::std::test::OracleMock; + +#[test] +fn success() { + let result = StorageWithinBlock { block_hash: hash, account, values }; + let recursive_proof = RecursiveProof { key_hash: 1, verification_key: [0; 114], proof: [0; 93] }; + + let _ = OracleMock::mock("get_account_with_storage_recursive").returns((result.serialize(), recursive_proof)); + + get_account_with_storage_recursive(ETHEREUM_MAINNET_ID, number, address, keys[0]); +} diff --git a/ethereum/circuits/lib/src/lib.nr b/ethereum/circuits/lib/src/lib.nr index 09c7cdf54..0b1f2edc6 100644 --- a/ethereum/circuits/lib/src/lib.nr +++ b/ethereum/circuits/lib/src/lib.nr @@ -4,6 +4,8 @@ mod header; mod header_int_test; mod account_with_storage; mod account_with_storage_int_test; +mod account_with_storage_recursive; +mod account_with_storage_recursive_int_test; mod receipt; mod receipt_int_test; mod log; diff --git a/ethereum/oracles/src/noir/oracles/recursive/getStorageOracle.ts b/ethereum/oracles/src/noir/oracles/recursive/getStorageOracle.ts index e78abd6f8..25fd29415 100644 --- a/ethereum/oracles/src/noir/oracles/recursive/getStorageOracle.ts +++ b/ethereum/oracles/src/noir/oracles/recursive/getStorageOracle.ts @@ -7,7 +7,7 @@ import { VerificationKey } from '../../circuit/vk.js'; export const getStorageOracle = async (args: NoirArguments): Promise => { const { blockNumber, address, storageKey, chainId } = decodeGetProofArguments(args); - const circuit = await MonorepoCircuit.create('../../', 'get_storage'); + const circuit = await MonorepoCircuit.create('../../', 'get_storage_recursive'); const vk = await VerificationKey.create(circuit.vkAsFieldsPath()); const { proofAsFields, verifierData } = await new GetStorageProver(circuit).prove( chainId, diff --git a/vlayer/ethereum/circuits/lib/src/token.nr b/vlayer/ethereum/circuits/lib/src/token.nr index f6a648803..47df18c31 100644 --- a/vlayer/ethereum/circuits/lib/src/token.nr +++ b/vlayer/ethereum/circuits/lib/src/token.nr @@ -1,5 +1,5 @@ use dep::ethereum::{ - account_with_storage::get_account_with_storage, misc::types::Address, + account_with_storage_recursive::get_account_with_storage_recursive, misc::types::Address, misc::bytes32::address_to_bytes32 }; use dep::std::field::bytes32_to_field; @@ -28,7 +28,7 @@ trait ERC20 { impl ERC20 for ERC20Token { fn get_balance(self, wallet_address: Address, block_number: u64) -> U128 { let storage_key = self.calculate_balance_storage_key(wallet_address); - let account = get_account_with_storage(self.chain_id, block_number, self.address, U256::into(storage_key)); + let account = get_account_with_storage_recursive(self.chain_id, block_number, self.address, U256::into(storage_key)); let balance = account.values[TOKEN_BALANCE_INDEX]; U128::from_integer(bytes32_to_field(balance)) diff --git a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml index d7521d88e..6b5c37d3d 100644 --- a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml +++ b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml @@ -1 +1 @@ -block_number = 19000000 +block_number = "0x000000000000000000000000000000000000000000000000000000000121eac0" From ee46af88c025863872234eb05d890e1e447907cb Mon Sep 17 00:00:00 2001 From: Arkadiusz Konior Date: Fri, 7 Jun 2024 11:00:42 +0200 Subject: [PATCH 2/2] is_dao_worthy_recursive --- .github/workflows/circuits_e2e.yaml | 27 ++++++++++++++++++- Nargo.toml | 1 + .../lib/src/account_with_storage_recursive.nr | 10 +++---- ...account_with_storage_recursive_int_test.nr | 10 ++++--- .../oracles/src/noir/oracles/server/app.ts | 2 +- .../src/noir/oracles/server/handlers.ts | 2 +- .../src/script/generateGetStorageVK.ts | 2 +- vlayer/ethereum/circuits/lib/src/token.nr | 11 +++++--- .../circuits/lib/src/token_int_test.nr | 10 +++++-- .../circuits/is_dao_worthy/Verifier.toml | 2 +- .../circuits/is_dao_worthy/src/main.nr | 2 +- .../is_dao_worthy_recursive/Nargo.toml | 8 ++++++ .../is_dao_worthy_recursive/Prover.toml | 4 +++ .../is_dao_worthy_recursive/Verifier.toml | 1 + .../is_dao_worthy_recursive/src/main.nr | 12 +++++++++ .../is_dao_worthy_recursive/src/main_test.nr | 27 +++++++++++++++++++ 16 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 vlayer/examples/circuits/is_dao_worthy_recursive/Nargo.toml create mode 100644 vlayer/examples/circuits/is_dao_worthy_recursive/Prover.toml create mode 100644 vlayer/examples/circuits/is_dao_worthy_recursive/Verifier.toml create mode 100644 vlayer/examples/circuits/is_dao_worthy_recursive/src/main.nr create mode 100644 vlayer/examples/circuits/is_dao_worthy_recursive/src/main_test.nr diff --git a/.github/workflows/circuits_e2e.yaml b/.github/workflows/circuits_e2e.yaml index e2b4650f7..2fae275ad 100644 --- a/.github/workflows/circuits_e2e.yaml +++ b/.github/workflows/circuits_e2e.yaml @@ -34,7 +34,20 @@ jobs: toolchain: nightly-2024-05-22 - name: Compile Circuit - run: nargo compile --workspace --deny-warnings + run: | + nargo compile --package get_header --deny-warnings + nargo compile --package get_account --deny-warnings + nargo compile --package get_storage --deny-warnings + nargo compile --package get_storage_recursive --deny-warnings + nargo compile --package get_receipt --deny-warnings + nargo compile --package get_transaction --deny-warnings + nargo compile --package get_log --deny-warnings + nargo compile --package is_dao_worthy --deny-warnings + nargo compile --package is_ape_owner --deny-warnings + + # We cannot use the `--deny-warnings` option in `is_dao_worthy_recursive` because the `verify_proof` method generates warnings + # that are actually informational messages from the compiler and cannot be ignored. + nargo compile --package is_dao_worthy_recursive - name: Start Oracle Server working-directory: ethereum/oracles @@ -54,6 +67,18 @@ jobs: nargo prove --package is_dao_worthy --oracle-resolver=http://localhost:5555 nargo prove --package is_ape_owner --oracle-resolver=http://localhost:5555 + - name: Generate verification key for recursive proof + working-directory: ethereum/oracles + run: | + # Verification key generation uses Barretenberg backend located at ~/.nargo/backends/acvm-backend-barretenberg/backend_binary. + # It is automatically installed during the execution of the `nargo prove` command in previous step. + yarn generate-get-storage-vk + + - name: Generate Recursive Proof + run: | + export NARGO_FOREIGN_CALL_TIMEOUT=100000 # miliseconds + nargo prove --package is_dao_worthy_recursive --oracle-resolver=http://localhost:5555 + - name: Verify Proof run: | nargo verify --package get_header diff --git a/Nargo.toml b/Nargo.toml index d9c4dc107..7df2926a9 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -10,6 +10,7 @@ members = [ "ethereum/circuits/get_log", "vlayer/ethereum/circuits/lib", "vlayer/examples/circuits/is_dao_worthy", + "vlayer/examples/circuits/is_dao_worthy_recursive", "vlayer/examples/circuits/is_ape_owner", "vlayer/examples/circuits/is_crypto_punk_owner", ] diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive.nr b/ethereum/circuits/lib/src/account_with_storage_recursive.nr index 11585de04..83333b103 100644 --- a/ethereum/circuits/lib/src/account_with_storage_recursive.nr +++ b/ethereum/circuits/lib/src/account_with_storage_recursive.nr @@ -1,8 +1,7 @@ +use crate::account_with_storage::StorageWithinBlock; use crate::misc::{fragment::Fragment, types::{Address, Bytes32, ADDRESS_LENGTH, BYTES32_LENGTH}}; use crate::serde::STORAGE_BLOCK_LEN; -use dep::std::verify_proof; -use crate::account_with_storage::StorageWithinBlock; -use dep::std::unsafe::zeroed; +use dep::std::{verify_proof, unsafe::zeroed}; struct RecursiveProof { key_hash: Field, @@ -26,19 +25,18 @@ pub fn get_account_with_storage_recursive( public_inputs.extend_back(address.serialize()); public_inputs.extend_back(storage_key.serialize()); public_inputs.extend_back(storage_within_block.serialize()); - let public_inputs_array: [Field; NUM_PUBLIC_INPUTS] = public_inputs.to_array(); verify_proof( verification_key.as_slice(), proof.as_slice(), - public_inputs_array.as_slice(), + public_inputs.to_array::().as_slice(), key_hash ); storage_within_block } -#[oracle(get_account_with_storage_recursive)] +#[oracle(get_storage_recursive)] unconstrained fn get_account_with_storage_recursive_oracle( chain_id: Field, block_number: u64, diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr index fd7a5231d..667707ec8 100644 --- a/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr +++ b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr @@ -1,16 +1,18 @@ use crate::account_with_storage_recursive::{get_account_with_storage_recursive, RecursiveProof}; use crate::account_with_storage::StorageWithinBlock; -use crate::fixtures::mainnet::paris::usdc_circle::{header::{number, hash}, account::{address, account} storage::{keys, values}}; +use crate::fixtures::mainnet::paris::usdc_circle::{header::{number, hash}, account::{address, account}, storage::{keys, values}}; use crate::chain::ETHEREUM_MAINNET_ID; use crate::misc::types::{Bytes32, Address}; use dep::std::test::OracleMock; +use dep::std::unsafe::zeroed; #[test] fn success() { let result = StorageWithinBlock { block_hash: hash, account, values }; - let recursive_proof = RecursiveProof { key_hash: 1, verification_key: [0; 114], proof: [0; 93] }; + // This is not a correct proof but it passes because nargo does not verify it. Nargo thinks that it's bb's job, but doesn't call bb. + let recursive_proof: RecursiveProof = zeroed(); - let _ = OracleMock::mock("get_account_with_storage_recursive").returns((result.serialize(), recursive_proof)); + let _ = OracleMock::mock("get_storage_recursive").returns((result.serialize(), recursive_proof)); - get_account_with_storage_recursive(ETHEREUM_MAINNET_ID, number, address, keys[0]); + let _ = get_account_with_storage_recursive(ETHEREUM_MAINNET_ID, number, address, keys[0]); } diff --git a/ethereum/oracles/src/noir/oracles/server/app.ts b/ethereum/oracles/src/noir/oracles/server/app.ts index 23273cc49..10b7d289d 100644 --- a/ethereum/oracles/src/noir/oracles/server/app.ts +++ b/ethereum/oracles/src/noir/oracles/server/app.ts @@ -18,7 +18,7 @@ jsonRPCServer.addMethod('get_account', getRpcOracleHandler.bind(this, getAccount jsonRPCServer.addMethod('get_proof', getRpcOracleHandler.bind(this, getProofOracle)); jsonRPCServer.addMethod('get_receipt', getRpcOracleHandler.bind(this, getReceiptOracle)); jsonRPCServer.addMethod('get_transaction', getRpcOracleHandler.bind(this, getTransactionOracle)); -jsonRPCServer.addMethod('recursive_get_storage', getOracleHandler.bind(this, getStorageOracle)); +jsonRPCServer.addMethod('get_storage_recursive', getOracleHandler.bind(this, getStorageOracle)); export function buildOracleServer( opts: Fastify.FastifyHttpOptions = {}, diff --git a/ethereum/oracles/src/noir/oracles/server/handlers.ts b/ethereum/oracles/src/noir/oracles/server/handlers.ts index 923ec1798..da250ebca 100644 --- a/ethereum/oracles/src/noir/oracles/server/handlers.ts +++ b/ethereum/oracles/src/noir/oracles/server/handlers.ts @@ -17,7 +17,7 @@ export type JSONRPCServerMethods = { get_proof(params: ForeignCallParams): ForeignCallResult; get_receipt(params: ForeignCallParams): ForeignCallResult; get_transaction(params: ForeignCallParams): ForeignCallResult; - recursive_get_storage(params: ForeignCallParams): ForeignCallResult; + get_storage_recursive(params: ForeignCallParams): ForeignCallResult; }; export interface ServerParams { diff --git a/ethereum/oracles/src/script/generateGetStorageVK.ts b/ethereum/oracles/src/script/generateGetStorageVK.ts index 55d3286fe..a58d26b33 100644 --- a/ethereum/oracles/src/script/generateGetStorageVK.ts +++ b/ethereum/oracles/src/script/generateGetStorageVK.ts @@ -1,7 +1,7 @@ import { MonorepoCircuit } from '../noir/circuit/circuit.js'; import { VerificationKey, generateVk } from '../noir/circuit/vk.js'; -const circuit = await MonorepoCircuit.create('../../', 'get_storage'); +const circuit = await MonorepoCircuit.create('../../', 'get_storage_recursive'); await generateVk(circuit.artefact.bytecode, circuit.vkPath(), circuit.vkAsFieldsPath()); const vk = await VerificationKey.create(circuit.vkAsFieldsPath()); // eslint-disable-next-line no-console diff --git a/vlayer/ethereum/circuits/lib/src/token.nr b/vlayer/ethereum/circuits/lib/src/token.nr index 47df18c31..206cea8e2 100644 --- a/vlayer/ethereum/circuits/lib/src/token.nr +++ b/vlayer/ethereum/circuits/lib/src/token.nr @@ -1,4 +1,5 @@ use dep::ethereum::{ + account_with_storage::get_account_with_storage, account_with_storage_recursive::get_account_with_storage_recursive, misc::types::Address, misc::bytes32::address_to_bytes32 }; @@ -22,13 +23,17 @@ impl ERC20Token { } trait ERC20 { - fn get_balance(self, wallet_address: Address, block_number: u64) -> U128 ; + fn get_balance(self, wallet_address: Address, block_number: u64, recursive: bool) -> U128; } impl ERC20 for ERC20Token { - fn get_balance(self, wallet_address: Address, block_number: u64) -> U128 { + fn get_balance(self, wallet_address: Address, block_number: u64, recursive: bool) -> U128 { let storage_key = self.calculate_balance_storage_key(wallet_address); - let account = get_account_with_storage_recursive(self.chain_id, block_number, self.address, U256::into(storage_key)); + let account = if recursive { + get_account_with_storage_recursive(self.chain_id, block_number, self.address, U256::into(storage_key)) + } else { + get_account_with_storage(self.chain_id, block_number, self.address, U256::into(storage_key)) + }; let balance = account.values[TOKEN_BALANCE_INDEX]; U128::from_integer(bytes32_to_field(balance)) diff --git a/vlayer/ethereum/circuits/lib/src/token_int_test.nr b/vlayer/ethereum/circuits/lib/src/token_int_test.nr index 402fc12b9..5e2ed9031 100644 --- a/vlayer/ethereum/circuits/lib/src/token_int_test.nr +++ b/vlayer/ethereum/circuits/lib/src/token_int_test.nr @@ -4,15 +4,21 @@ mod test_ERC20Token { use dep::ethereum::fixtures::mainnet::{ paris::usdc_circle::header::{block_header_partial as paris_block_header_partial, block_header_rlp as paris_block_header_rlp}, paris::usdc_circle::header::{hash, number, state_root, transactions_root, receipts_root}, - paris::usdc_circle::account::account, + paris::usdc_circle::account::account, paris::usdc_circle::storage::values, paris::usdc_circle::state_proof::proof_input_serialized as state_proof_input_serialized, paris::usdc_circle::storage_proof::proofs_serialized }; use dep::ethereum::uint256::U256; use crate::chain_id::MAINNET; + use dep::ethereum::account_with_storage_recursive::RecursiveProof; + use dep::ethereum::account_with_storage::StorageWithinBlock; #[test] fn success() { + let result = StorageWithinBlock { block_hash: hash, account, values }; + let recursive_proof = RecursiveProof { key_hash: 1, verification_key: [0; 114], proof: [0; 93] }; + + let _ = OracleMock::mock("get_storage_recursive").returns((result.serialize(), recursive_proof)); let _ = OracleMock::mock("get_header").returns((paris_block_header_partial, paris_block_header_rlp)); let _ = OracleMock::mock("get_proof").returns((account, state_proof_input_serialized, proofs_serialized[0])); @@ -29,7 +35,7 @@ mod test_ERC20Token { 0x55, 0xFE, 0x00, 0x2a, 0xef, 0xF0, 0x2F, 0x77, 0x36, 0x4d, 0xe3, 0x39, 0xa1, 0x29, 0x29, 0x23, 0xA1, 0x58, 0x44, 0xB8 ]; let block_number = 19000000; - let balance = usdc_token.get_balance(circle_address, block_number); + let balance = usdc_token.get_balance(circle_address, block_number, false); let expected_usdc_balnce_of_circle = U128::from_integer(125761774888720); assert_eq(expected_usdc_balnce_of_circle, balance); } diff --git a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml index 6b5c37d3d..d7521d88e 100644 --- a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml +++ b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml @@ -1 +1 @@ -block_number = "0x000000000000000000000000000000000000000000000000000000000121eac0" +block_number = 19000000 diff --git a/vlayer/examples/circuits/is_dao_worthy/src/main.nr b/vlayer/examples/circuits/is_dao_worthy/src/main.nr index 250bd8967..07d2235ee 100644 --- a/vlayer/examples/circuits/is_dao_worthy/src/main.nr +++ b/vlayer/examples/circuits/is_dao_worthy/src/main.nr @@ -6,7 +6,7 @@ mod main_test; global MIN_BALANCE = U128::from_integer(100_000_000_000); // $100k fn main(wallet_address: Address, block_number: pub u64) { - let wallet_balance = USDC.get_balance(wallet_address, block_number); + let wallet_balance = USDC.get_balance(wallet_address, block_number, false); let is_balance_greater_or_equal = MIN_BALANCE <= wallet_balance; assert(is_balance_greater_or_equal, "Insufficient USDC balance"); diff --git a/vlayer/examples/circuits/is_dao_worthy_recursive/Nargo.toml b/vlayer/examples/circuits/is_dao_worthy_recursive/Nargo.toml new file mode 100644 index 000000000..502e862b1 --- /dev/null +++ b/vlayer/examples/circuits/is_dao_worthy_recursive/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "is_dao_worthy_recursive" +type = "bin" +compiler_version = ">=0.30.0" + +[dependencies] +ethereum = { path = "../../../../ethereum/circuits/lib" } +token = { path = "../../../ethereum/circuits/lib" } diff --git a/vlayer/examples/circuits/is_dao_worthy_recursive/Prover.toml b/vlayer/examples/circuits/is_dao_worthy_recursive/Prover.toml new file mode 100644 index 000000000..c77cac23d --- /dev/null +++ b/vlayer/examples/circuits/is_dao_worthy_recursive/Prover.toml @@ -0,0 +1,4 @@ +block_number = 19000000 + +# Circle address +wallet_address = [ 0x55, 0xfe, 0x00, 0x2a, 0xef, 0xf0, 0x2f, 0x77, 0x36, 0x4d, 0xe3, 0x39, 0xa1, 0x29, 0x29, 0x23, 0xa1, 0x58, 0x44, 0xb8 ] diff --git a/vlayer/examples/circuits/is_dao_worthy_recursive/Verifier.toml b/vlayer/examples/circuits/is_dao_worthy_recursive/Verifier.toml new file mode 100644 index 000000000..d7521d88e --- /dev/null +++ b/vlayer/examples/circuits/is_dao_worthy_recursive/Verifier.toml @@ -0,0 +1 @@ +block_number = 19000000 diff --git a/vlayer/examples/circuits/is_dao_worthy_recursive/src/main.nr b/vlayer/examples/circuits/is_dao_worthy_recursive/src/main.nr new file mode 100644 index 000000000..7ce7056db --- /dev/null +++ b/vlayer/examples/circuits/is_dao_worthy_recursive/src/main.nr @@ -0,0 +1,12 @@ +use dep::ethereum::misc::types::Address; +use dep::token::token_list::mainnet::USDC; + +mod main_test; + +global MIN_BALANCE = U128::from_integer(100_000_000_000); // $100k + +fn main(wallet_address: Address, block_number: pub u64) { + let wallet_balance = USDC.get_balance(wallet_address, block_number, true); + + assert(MIN_BALANCE <= wallet_balance, "Insufficient USDC balance"); +} diff --git a/vlayer/examples/circuits/is_dao_worthy_recursive/src/main_test.nr b/vlayer/examples/circuits/is_dao_worthy_recursive/src/main_test.nr new file mode 100644 index 000000000..153534176 --- /dev/null +++ b/vlayer/examples/circuits/is_dao_worthy_recursive/src/main_test.nr @@ -0,0 +1,27 @@ +mod is_dao_worthy_main { + use dep::std::test::OracleMock; + use dep::ethereum::fixtures::mainnet::{ + paris::usdc_circle::header::{hash, block_header_partial as paris_block_header_partial, block_header_rlp as paris_block_header_rlp}, + paris::usdc_circle::account::account, paris::usdc_circle::storage::values, + paris::usdc_circle::state_proof::proof_input_serialized as state_proof_input_serialized, + paris::usdc_circle::storage_proof::proofs_serialized + }; + use dep::ethereum::{account_with_storage_recursive::RecursiveProof, account_with_storage::StorageWithinBlock}; + use crate::main; + + #[test] + fn success_greater_then() { + let result = StorageWithinBlock { block_hash: hash, account, values }; + let recursive_proof = RecursiveProof { key_hash: 1, verification_key: [0; 114], proof: [0; 93] }; + + let _ = OracleMock::mock("get_storage_recursive").returns((result.serialize(), recursive_proof)); + let _ = OracleMock::mock("get_header").returns((paris_block_header_partial, paris_block_header_rlp)); + let _ = OracleMock::mock("get_proof").returns((account, state_proof_input_serialized, proofs_serialized[0])); + + let block_number = 19_000_000; + let circle_address = [ + 0x55, 0xfe, 0x00, 0x2a, 0xef, 0xf0, 0x2f, 0x77, 0x36, 0x4d, 0xe3, 0x39, 0xa1, 0x29, 0x29, 0x23, 0xa1, 0x58, 0x44, 0xb8 + ]; + main(circle_address, block_number); + } +}