diff --git a/apps/contracts/audit_registry/src/lib.rs b/apps/contracts/audit_registry/src/lib.rs index d15b206..e0b8420 100644 --- a/apps/contracts/audit_registry/src/lib.rs +++ b/apps/contracts/audit_registry/src/lib.rs @@ -59,7 +59,17 @@ pub struct AuditAnchor { pub anchored_at_ledger: u32, } - /// Enumeration of all storage keys used by this contract. +/// Consolidated read-only view of anchor status for a reading hash. +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AnchorStatus { + /// Whether `reading_hash` has been anchored. + pub is_anchored: bool, + /// Ledger sequence at anchor time; `0` when `is_anchored` is `false`. + pub anchored_at_ledger: u32, +} + +/// Enumeration of all storage keys used by this contract. #[contracttype] pub enum DataKey { /// `Address` — the contract administrator. @@ -175,6 +185,15 @@ impl AuditRegistry { ((b0 << 8) | b1) % 1024 } + fn lookup_ledger(env: Env, reading_hash: BytesN<32>) -> Option { + let bucket_id = Self::get_bucket_id(&reading_hash); + let bucket: Map, u32> = env + .storage() + .persistent() + .get(&DataKey::Bucket(bucket_id))?; + bucket.get(reading_hash) + } + /// Anchor a reading hash on-chain. Only the registered `api_signer` may call this. /// /// # Arguments @@ -266,9 +285,7 @@ impl AuditRegistry { /// } /// ``` pub fn verify(env: Env, reading_hash: BytesN<32>) -> Option { - let bucket_id = Self::get_bucket_id(&reading_hash); - let bucket: Map, u32> = env.storage().persistent().get(&DataKey::Bucket(bucket_id))?; - let anchored_at_ledger = bucket.get(reading_hash.clone())?; + let anchored_at_ledger = Self::lookup_ledger(env.clone(), reading_hash.clone())?; Some(AuditAnchor { reading_hash, anchored_at_ledger, @@ -277,14 +294,38 @@ impl AuditRegistry { /// Returns `true` if `reading_hash` has been anchored, `false` otherwise. pub fn is_anchored(env: Env, reading_hash: BytesN<32>) -> bool { - let bucket_id = Self::get_bucket_id(&reading_hash); - let bucket: Option, u32>> = env.storage().persistent().get(&DataKey::Bucket(bucket_id)); - match bucket { - Some(b) => b.contains_key(reading_hash), - None => false, + Self::lookup_ledger(env, reading_hash).is_some() + } + + /// Returns consolidated anchor status for `reading_hash` in a single call. + /// + /// Prefer this over separate `is_anchored` + `verify` calls when you need + /// both the presence flag and the anchor ledger sequence. + pub fn anchor_status(env: Env, reading_hash: BytesN<32>) -> AnchorStatus { + match Self::lookup_ledger(env, reading_hash) { + Some(anchored_at_ledger) => AnchorStatus { + is_anchored: true, + anchored_at_ledger, + }, + None => AnchorStatus { + is_anchored: false, + anchored_at_ledger: 0, + }, } } + /// Returns the ledger sequence at which `reading_hash` was anchored. + /// + /// Returns `None` when the hash has not been anchored. + pub fn anchored_at_ledger(env: Env, reading_hash: BytesN<32>) -> Option { + Self::lookup_ledger(env, reading_hash) + } + + /// Returns the persistent storage bucket index (0–1023) for `reading_hash`. + pub fn bucket_for_hash(_env: Env, reading_hash: BytesN<32>) -> u32 { + Self::get_bucket_id(&reading_hash) + } + /// Returns the total number of reading hashes anchored so far. pub fn total_anchors(env: Env) -> u32 { env.storage() @@ -336,11 +377,13 @@ impl AuditRegistry { max_extension: u32, ) { Self::require_admin(&env); - env.storage().persistent().extend_ttl_with_limits( + if extend_to < min_extension || extend_to > max_extension { + return; + } + env.storage().persistent().extend_ttl( &DataKey::Bucket(bucket_id), - extend_to, min_extension, - max_extension, + extend_to, ); } @@ -364,9 +407,12 @@ impl AuditRegistry { max_extension: u32, ) { Self::require_admin(&env); + if extend_to < min_extension || extend_to > max_extension { + return; + } env.storage() .instance() - .extend_ttl_with_limits(extend_to, min_extension, max_extension); + .extend_ttl(min_extension, extend_to); } } @@ -377,7 +423,12 @@ impl AuditRegistry { #[cfg(test)] mod tests { use super::*; - use soroban_sdk::{testutils::Address as _, Env}; + use soroban_sdk::{ + testutils::storage::{Instance, Persistent}, + testutils::Address as _, + testutils::Ledger, + Env, + }; fn setup() -> (Env, soroban_sdk::Address, AuditRegistryClient<'static>) { let env = Env::default(); @@ -510,8 +561,11 @@ mod tests { fn test_total_anchors_increments() { let (env, api_signer, client) = setup(); for i in 0u8..5 { - client - .anchor(&api_signer, &BytesN::from_array(&env, &[i; 32]), &make_nonce(&env, i)); + client.anchor( + &api_signer, + &BytesN::from_array(&env, &[i; 32]), + &make_nonce(&env, i), + ); } assert_eq!(client.total_anchors(), 5); } @@ -593,31 +647,66 @@ mod tests { #[test] fn test_extend_bucket_ttl() { let (env, api_signer, client) = setup(); + let contract_id = client.address.clone(); let h = hash(&env); let n = make_nonce(&env, 1); - client.anchor(&api_signer, &h, &n).unwrap(); + client.anchor(&api_signer, &h, &n); let bucket_id = AuditRegistry::get_bucket_id(&h); - let before = env - .storage() - .persistent() - .get_ttl(&DataKey::Bucket(bucket_id)); - client.extend_bucket_ttl(bucket_id, u32::MAX, before + 50); - let after = env - .storage() - .persistent() - .get_ttl(&DataKey::Bucket(bucket_id)); + let before = env.as_contract(&contract_id, || { + env.storage() + .persistent() + .get_ttl(&DataKey::Bucket(bucket_id)) + }); + client.extend_bucket_ttl(&bucket_id, &before, &(before + 50)); + let after = env.as_contract(&contract_id, || { + env.storage() + .persistent() + .get_ttl(&DataKey::Bucket(bucket_id)) + }); assert!(after >= before); } #[test] fn test_extend_contract_ttl() { let (env, _api_signer, client) = setup(); - let before = env.storage().instance().get_ttl(); - client.extend_contract_ttl(u32::MAX, before + 50); - let after = env.storage().instance().get_ttl(); + let contract_id = client.address.clone(); + let before = env.as_contract(&contract_id, || env.storage().instance().get_ttl()); + client.extend_contract_ttl(&before, &(before + 50)); + let after = env.as_contract(&contract_id, || env.storage().instance().get_ttl()); assert!(after >= before); } + #[test] + fn test_anchor_status_not_anchored() { + let (env, _api_signer, client) = setup(); + let h = BytesN::from_array(&env, &[9u8; 32]); + assert_eq!( + client.anchor_status(&h), + AnchorStatus { + is_anchored: false, + anchored_at_ledger: 0, + } + ); + assert!(client.anchored_at_ledger(&h).is_none()); + } + + #[test] + fn test_anchor_status_after_anchor() { + let (env, api_signer, client) = setup(); + env.ledger().set_sequence_number(42); + let h = hash(&env); + client.anchor(&api_signer, &h, &make_nonce(&env, 1)); + assert_eq!( + client.anchor_status(&h), + AnchorStatus { + is_anchored: true, + anchored_at_ledger: 42, + } + ); + assert_eq!(client.anchored_at_ledger(&h), Some(42)); + assert_eq!(client.bucket_for_hash(&h), AuditRegistry::get_bucket_id(&h)); + } + #[test] fn test_issue_281_bucket_collision() { let (env, api_signer, client) = setup(); @@ -627,62 +716,19 @@ mod tests { let mut h1_arr = [0u8; 32]; h1_arr[2] = 1; let h1 = BytesN::from_array(&env, &h1_arr); - + let mut h2_arr = [0u8; 32]; h2_arr[2] = 2; let h2 = BytesN::from_array(&env, &h2_arr); - + client.anchor(&api_signer, &h1, &make_nonce(&env, 1)); client.anchor(&api_signer, &h2, &make_nonce(&env, 2)); - + assert!(client.is_anchored(&h1)); assert!(client.is_anchored(&h2)); assert_eq!(client.total_anchors(), 2); } - - #[test] - fn test_admin_lookup() { - let (env, client) = setup(); - let admin = client.admin(); - assert_eq!(admin, Address::generate(&env)); - } - - // --- Invariant: zero and negative kwh_stroops must be rejected --- - - #[test] - #[should_panic(expected = "kwh must be positive")] - fn test_zero_kwh_rejected() { - let (env, client) = setup(); - let signer = soroban_sdk::testutils::ed25519::Signer::generate(&env); - let reading_hash = BytesN::from_array(&env, &[2u8; 32]); - let sig = signer.sign(&env, &Bytes::from_slice(&env, reading_hash.to_array().as_ref())); - client.anchor( - &reading_hash, - &signer.public_key(&env), - &sig, - &0_i128, - &soroban_sdk::String::from_str(&env, "METER-001"), - &1_700_000_000_u64, - ); - } - - #[test] - #[should_panic(expected = "kwh must be positive")] - fn test_negative_kwh_rejected() { - let (env, client) = setup(); - let signer = soroban_sdk::testutils::ed25519::Signer::generate(&env); - let reading_hash = BytesN::from_array(&env, &[3u8; 32]); - let sig = signer.sign(&env, &Bytes::from_slice(&env, reading_hash.to_array().as_ref())); - client.anchor( - &reading_hash, - &signer.public_key(&env), - &sig, - &-1_i128, - &soroban_sdk::String::from_str(&env, "METER-001"), - &1_700_000_000_u64, - ); - } } #[cfg(test)] -mod verify_integration_test; \ No newline at end of file +mod verify_integration_test; diff --git a/apps/contracts/audit_registry/src/verify_integration_test.rs b/apps/contracts/audit_registry/src/verify_integration_test.rs index 9e0993d..db26d93 100644 --- a/apps/contracts/audit_registry/src/verify_integration_test.rs +++ b/apps/contracts/audit_registry/src/verify_integration_test.rs @@ -6,8 +6,8 @@ #![cfg(test)] -use audit_registry::{AuditRegistry, AuditRegistryClient, Error}; -use soroban_sdk::{testutils::Address as _, Address, BytesN, Env}; +use crate::{AnchorStatus, AuditRegistry, AuditRegistryClient, Error}; +use soroban_sdk::{testutils::Address as _, testutils::Ledger, Address, BytesN, Env}; fn setup() -> (Env, Address, AuditRegistryClient<'static>) { let env = Env::default(); @@ -24,6 +24,10 @@ fn make_hash(env: &Env, byte: u8) -> BytesN<32> { BytesN::from_array(env, &[byte; 32]) } +fn make_nonce(env: &Env, val: u8) -> BytesN<32> { + BytesN::from_array(env, &[val; 32]) +} + // ── verify returns None before anchoring ───────────────────────────────────── #[test] @@ -38,7 +42,7 @@ fn verify_returns_none_for_unanchored_hash() { fn verify_returns_anchor_with_correct_reading_hash() { let (env, signer, client) = setup(); let h = make_hash(&env, 0x42); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); let anchor = client.verify(&h).expect("must be Some after anchor"); assert_eq!(anchor.reading_hash, h); } @@ -46,10 +50,9 @@ fn verify_returns_anchor_with_correct_reading_hash() { #[test] fn verify_records_ledger_sequence_at_anchor_time() { let (env, signer, client) = setup(); - // Advance ledger to a known sequence - env.ledger().with_mut(|l| l.sequence_number = 999); + env.ledger().set_sequence_number(999); let h = make_hash(&env, 0x10); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); let anchor = client.verify(&h).expect("must be Some"); assert_eq!(anchor.anchored_at_ledger, 999); } @@ -57,13 +60,11 @@ fn verify_records_ledger_sequence_at_anchor_time() { #[test] fn verify_ledger_sequence_is_not_current_ledger_if_anchored_earlier() { let (env, signer, client) = setup(); - env.ledger().with_mut(|l| l.sequence_number = 100); + env.ledger().set_sequence_number(100); let h = make_hash(&env, 0x20); - client.anchor(&signer, &h).unwrap(); - // Advance ledger after anchoring - env.ledger().with_mut(|l| l.sequence_number = 500); + client.anchor(&signer, &h, &make_nonce(&env, 1)); + env.ledger().set_sequence_number(500); let anchor = client.verify(&h).expect("must be Some"); - // anchored_at_ledger must reflect the time of anchor, not the current ledger assert_eq!(anchor.anchored_at_ledger, 100); } @@ -73,7 +74,7 @@ fn verify_ledger_sequence_is_not_current_ledger_if_anchored_earlier() { fn verify_is_idempotent() { let (env, signer, client) = setup(); let h = make_hash(&env, 0x55); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); let a1 = client.verify(&h).expect("first verify must be Some"); let a2 = client.verify(&h).expect("second verify must be Some"); assert_eq!(a1.reading_hash, a2.reading_hash); @@ -87,10 +88,10 @@ fn verify_distinguishes_two_hashes() { let (env, signer, client) = setup(); let h1 = make_hash(&env, 0xAA); let h2 = make_hash(&env, 0xBB); - env.ledger().with_mut(|l| l.sequence_number = 1); - client.anchor(&signer, &h1).unwrap(); - env.ledger().with_mut(|l| l.sequence_number = 2); - client.anchor(&signer, &h2).unwrap(); + env.ledger().set_sequence_number(1); + client.anchor(&signer, &h1, &make_nonce(&env, 1)); + env.ledger().set_sequence_number(2); + client.anchor(&signer, &h2, &make_nonce(&env, 2)); let a1 = client.verify(&h1).expect("h1 must be anchored"); let a2 = client.verify(&h2).expect("h2 must be anchored"); @@ -105,26 +106,53 @@ fn verify_distinguishes_two_hashes() { #[test] fn verify_unchanged_after_rejected_duplicate_anchor() { let (env, signer, client) = setup(); - env.ledger().with_mut(|l| l.sequence_number = 10); + env.ledger().set_sequence_number(10); let h = make_hash(&env, 0x77); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); - // second anchor attempt must fail - env.ledger().with_mut(|l| l.sequence_number = 20); - assert_eq!(client.anchor(&signer, &h), Err(Error::AlreadyAnchored)); + env.ledger().set_sequence_number(20); + assert_eq!( + client.try_anchor(&signer, &h, &make_nonce(&env, 2)), + Err(Ok(Error::AlreadyAnchored)) + ); - // verify must still return the original anchor (ledger 10, not 20) let anchor = client.verify(&h).expect("must still be anchored"); assert_eq!(anchor.anchored_at_ledger, 10); } +// ── anchor_status helper view ──────────────────────────────────────────────── + +#[test] +fn anchor_status_matches_verify() { + let (env, signer, client) = setup(); + let h = make_hash(&env, 0x33); + assert_eq!( + client.anchor_status(&h), + AnchorStatus { + is_anchored: false, + anchored_at_ledger: 0, + } + ); + + env.ledger().set_sequence_number(77); + client.anchor(&signer, &h, &make_nonce(&env, 1)); + assert_eq!( + client.anchor_status(&h), + AnchorStatus { + is_anchored: true, + anchored_at_ledger: 77, + } + ); + assert_eq!(client.anchored_at_ledger(&h), Some(77)); +} + // ── boundary hash values ────────────────────────────────────────────────────── #[test] fn verify_works_with_all_zeros_hash() { let (env, signer, client) = setup(); let h = BytesN::from_array(&env, &[0x00u8; 32]); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); assert!(client.verify(&h).is_some()); } @@ -132,6 +160,6 @@ fn verify_works_with_all_zeros_hash() { fn verify_works_with_all_ones_hash() { let (env, signer, client) = setup(); let h = BytesN::from_array(&env, &[0xFFu8; 32]); - client.anchor(&signer, &h).unwrap(); + client.anchor(&signer, &h, &make_nonce(&env, 1)); assert!(client.verify(&h).is_some()); } diff --git a/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_after_anchor.1.json b/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_after_anchor.1.json new file mode 100644 index 0000000..c1401d3 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_after_anchor.1.json @@ -0,0 +1,286 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 42, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 257 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 257 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + }, + "val": { + "u32": 42 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4137 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 57 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312041 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_not_anchored.1.json b/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_not_anchored.1.json new file mode 100644 index 0000000..39ac8c5 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/tests/test_anchor_status_not_anchored.1.json @@ -0,0 +1,128 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/tests/test_extend_bucket_ttl.1.json b/apps/contracts/audit_registry/test_snapshots/tests/test_extend_bucket_ttl.1.json new file mode 100644 index 0000000..bb002d6 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/tests/test_extend_bucket_ttl.1.json @@ -0,0 +1,343 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "extend_bucket_ttl", + "args": [ + { + "u32": 257 + }, + { + "u32": 4095 + }, + { + "u32": 4145 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 257 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 257 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + }, + "val": { + "u32": 0 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4145 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 15 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/tests/test_extend_contract_ttl.1.json b/apps/contracts/audit_registry/test_snapshots/tests/test_extend_contract_ttl.1.json new file mode 100644 index 0000000..0f8dd88 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/tests/test_extend_contract_ttl.1.json @@ -0,0 +1,183 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "extend_contract_ttl", + "args": [ + { + "u32": 4095 + }, + { + "u32": 4145 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4145 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4145 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/anchor_status_matches_verify.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/anchor_status_matches_verify.1.json new file mode 100644 index 0000000..fcecd38 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/anchor_status_matches_verify.1.json @@ -0,0 +1,286 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "3333333333333333333333333333333333333333333333333333333333333333" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 77, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 819 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 819 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "3333333333333333333333333333333333333333333333333333333333333333" + }, + "val": { + "u32": 77 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4172 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 92 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312076 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_distinguishes_two_hashes.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_distinguishes_two_hashes.1.json new file mode 100644 index 0000000..3972590 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_distinguishes_two_hashes.1.json @@ -0,0 +1,442 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 2, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 682 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 682 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + "val": { + "u32": 1 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4096 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 955 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 955 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "val": { + "u32": 2 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4097 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 16 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0202020202020202020202020202020202020202020202020202020202020202" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 17 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 2 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312000 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312001 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_is_idempotent.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_is_idempotent.1.json new file mode 100644 index 0000000..e8def2b --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_is_idempotent.1.json @@ -0,0 +1,285 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "5555555555555555555555555555555555555555555555555555555555555555" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 341 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 341 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "5555555555555555555555555555555555555555555555555555555555555555" + }, + "val": { + "u32": 0 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 15 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_ledger_sequence_is_not_current_ledger_if_anchored_earlier.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_ledger_sequence_is_not_current_ledger_if_anchored_earlier.1.json new file mode 100644 index 0000000..0d7b844 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_ledger_sequence_is_not_current_ledger_if_anchored_earlier.1.json @@ -0,0 +1,284 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "2020202020202020202020202020202020202020202020202020202020202020" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 500, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 32 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 32 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "2020202020202020202020202020202020202020202020202020202020202020" + }, + "val": { + "u32": 100 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4195 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 115 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312099 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_records_ledger_sequence_at_anchor_time.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_records_ledger_sequence_at_anchor_time.1.json new file mode 100644 index 0000000..3904566 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_records_ledger_sequence_at_anchor_time.1.json @@ -0,0 +1,284 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "1010101010101010101010101010101010101010101010101010101010101010" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 999, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 16 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 16 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "1010101010101010101010101010101010101010101010101010101010101010" + }, + "val": { + "u32": 999 + } + } + ] + } + } + }, + "ext": "v0" + }, + 5094 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 1014 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312998 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_anchor_with_correct_reading_hash.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_anchor_with_correct_reading_hash.1.json new file mode 100644 index 0000000..5dd8c8a --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_anchor_with_correct_reading_hash.1.json @@ -0,0 +1,284 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "4242424242424242424242424242424242424242424242424242424242424242" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 578 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 578 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "4242424242424242424242424242424242424242424242424242424242424242" + }, + "val": { + "u32": 0 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 15 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_none_for_unanchored_hash.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_none_for_unanchored_hash.1.json new file mode 100644 index 0000000..85bb5ee --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_returns_none_for_unanchored_hash.1.json @@ -0,0 +1,127 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_unchanged_after_rejected_duplicate_anchor.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_unchanged_after_rejected_duplicate_anchor.1.json new file mode 100644 index 0000000..a3ff734 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_unchanged_after_rejected_duplicate_anchor.1.json @@ -0,0 +1,285 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "7777777777777777777777777777777777777777777777777777777777777777" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 20, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 887 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 887 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "7777777777777777777777777777777777777777777777777777777777777777" + }, + "val": { + "u32": 10 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4105 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 25 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6312009 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_ones_hash.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_ones_hash.1.json new file mode 100644 index 0000000..02577be --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_ones_hash.1.json @@ -0,0 +1,284 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 1023 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 1023 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }, + "val": { + "u32": 0 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 15 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_zeros_hash.1.json b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_zeros_hash.1.json new file mode 100644 index 0000000..49ed8f2 --- /dev/null +++ b/apps/contracts/audit_registry/test_snapshots/verify_integration_test/verify_works_with_all_zeros_hash.1.json @@ -0,0 +1,284 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "anchor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 23, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 0 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Bucket" + }, + { + "u32": 0 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "val": { + "u32": 0 + } + } + ] + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Nonce" + }, + { + "bytes": "0101010101010101010101010101010101010101010101010101010101010101" + } + ] + }, + "durability": "temporary", + "val": { + "bool": true + } + } + }, + "ext": "v0" + }, + 15 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "ApiSigner" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TotalAnchors" + } + ] + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "vec": [ + { + "symbol": "Version" + } + ] + }, + "val": { + "string": "1.0.0" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/apps/contracts/energy_token/src/lib.rs b/apps/contracts/energy_token/src/lib.rs index a86628e..0419a55 100644 --- a/apps/contracts/energy_token/src/lib.rs +++ b/apps/contracts/energy_token/src/lib.rs @@ -2,7 +2,7 @@ //! //! SEP-41 fungible certificate token representing verified renewable energy. //! **1000 token units = 1 kWh** (decimals = 3; 1 unit = 0.001 kWh). -//! Generation is cryptographically anchored on-chain via the `audit_registry` contract. +//! Generation is cryptographically anchored on-chain via the `audit_registry` contract.. //! //! ## Roles //! | Role | Description | @@ -1218,7 +1218,131 @@ mod tests { assert_eq!(from, user); assert_eq!(amount, 200_i128); } + + // ── Access control tests for set_minter and admin (issue #562) ────────── + + /// Admin can call set_minter successfully; the new minter can then mint. + #[test] + fn test_set_minter_by_admin_succeeds() { + let (env, client) = setup(); + let admin = client.admin(); + let new_minter = Address::generate(&env); + // Admin rotates the minter + client.set_minter(&admin, &new_minter); + // New minter should be able to mint (mock_all_auths is active) + let user = Address::generate(&env); + client.mint(&user, &500_i128); + assert_eq!(client.balance(&user), 500_i128); + } + + /// A random non-admin address must not be able to call set_minter. + #[test] + #[should_panic] + fn test_set_minter_by_non_admin_panics() { + let (env, client) = setup(); + let non_admin = Address::generate(&env); + let new_minter = Address::generate(&env); + client.set_minter(&non_admin, &new_minter); + } + + /// The current minter address must not be able to call set_minter + /// (role separation: minter cannot self-promote or reassign the role). + #[test] + #[should_panic] + fn test_set_minter_by_minter_itself_panics() { + let env = Env::default(); + env.mock_all_auths(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + client.initialize(&admin, &minter); + // Minter tries to change the minter — must panic because it is not the admin + let new_minter = Address::generate(&env); + // Disable mock_all_auths so only the minter signs + // We use a fresh env without mock_all_auths for this check. + // Since require_auth on admin will fail when minter signs: + // (in mock_all_auths context every call is authorised so we verify via + // a contract-level guard instead — pass minter as the `new_minter` arg + // but call with a non-admin caller address to hit the auth path) + client.set_minter(&minter, &new_minter); + } + + /// admin() returns the address set during initialization. + #[test] + fn test_admin_address_accessible() { + let env = Env::default(); + env.mock_all_auths(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + client.initialize(&admin, &minter); + assert_eq!(client.admin(), admin); + } + + /// set_minter with the same address is idempotent — no panic, storage is just + /// overwritten with the same value. + #[test] + fn test_set_minter_to_same_address_is_idempotent() { + let env = Env::default(); + env.mock_all_auths(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + client.initialize(&admin, &minter); + // Calling set_minter with the current minter address should succeed silently + client.set_minter(&admin, &minter); + // Minting still works + let user = Address::generate(&env); + client.mint(&user, &100_i128); + assert_eq!(client.balance(&user), 100_i128); + } + + /// Calling initialize a second time must panic with "already initialized". + #[test] + #[should_panic(expected = "already initialized")] + fn test_double_initialize_panics() { + let (env, client) = setup(); + let a = Address::generate(&env); + // Second call to initialize must panic + client.initialize(&a, &a); + } + + /// After set_minter, a newly minted balance goes to the specified recipient. + /// Verifies the minter role update propagates correctly through the mint path. + #[test] + fn test_set_minter_updates_active_minter() { + let (env, client) = setup(); + let admin = client.admin(); + let new_minter = Address::generate(&env); + client.set_minter(&admin, &new_minter); + // Mint under the new minter context (mock_all_auths covers the new minter) + let recipient = Address::generate(&env); + client.mint(&recipient, &250_i128); + assert_eq!(client.balance(&recipient), 250_i128); + assert_eq!(client.total_supply(), 250_i128); + } + + /// Admin-set minter rotation does not affect existing balances. + #[test] + fn test_set_minter_does_not_affect_existing_balances() { + let (env, client) = setup(); + let holder = Address::generate(&env); + client.mint(&holder, &1_000_i128); + // Rotate minter + let admin = client.admin(); + let new_minter = Address::generate(&env); + client.set_minter(&admin, &new_minter); + // Existing balance is untouched + assert_eq!(client.balance(&holder), 1_000_i128); + assert_eq!(client.total_supply(), 1_000_i128); + } } #[cfg(test)] -mod overflow_tests; \ No newline at end of file +mod overflow_tests; + +#[cfg(test)] +mod storage_cost_tests; \ No newline at end of file diff --git a/apps/contracts/energy_token/src/storage_cost_tests.rs b/apps/contracts/energy_token/src/storage_cost_tests.rs new file mode 100644 index 0000000..ae258af --- /dev/null +++ b/apps/contracts/energy_token/src/storage_cost_tests.rs @@ -0,0 +1,316 @@ +//! Storage cost estimation tests for `energy_token` (issue #564). +//! +//! These tests exercise each contract method and print a summary of which +//! Soroban storage tiers (instance / persistent / temporary) are read and +//! written, along with the expected number of ledger-entry operations. +//! +//! They serve as living documentation — if a future refactor changes the +//! storage layout the test assertions will catch the behavioural change. +//! +//! Run with: +//! ```bash +//! cd apps/contracts +//! cargo test -p energy-token storage_cost -- --nocapture +//! ``` + +#[cfg(test)] +mod storage_cost_tests { + use crate::{EnergyToken, EnergyTokenClient}; + use soroban_sdk::{testutils::Address as _, Address, Env}; + + // ── helpers ────────────────────────────────────────────────────────────── + + fn setup() -> (Env, EnergyTokenClient<'static>, Address, Address) { + let env = Env::default(); + env.mock_all_auths(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + client.initialize(&admin, &minter); + (env, client, admin, minter) + } + + // ── initialize ─────────────────────────────────────────────────────────── + + /// `initialize` writes 5 instance-storage keys: + /// Admin, Minter, TotalMinted, TotalBurned, Paused. + /// Cost: 1 instance ledger-entry write (all instance keys share one entry). + #[test] + fn estimate_initialize_storage_ops() { + let env = Env::default(); + env.mock_all_auths(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + client.initialize(&admin, &minter); + // Post-condition: instance data is accessible + assert_eq!(client.admin(), admin); + println!( + "[storage_cost] initialize: 5 instance-key writes (1 instance ledger entry)" + ); + } + + // ── mint ───────────────────────────────────────────────────────────────── + + /// `mint` (first call for an address): + /// reads — Minter(instance), balance(persistent) [miss → 0], TotalMinted(instance) + /// writes — balance(persistent) [new entry], TotalMinted(instance) + /// + /// `mint` (subsequent call to same address): + /// reads — Minter(instance), balance(persistent), TotalMinted(instance) + /// writes — balance(persistent) [update], TotalMinted(instance) + /// + /// Ledger entry ops: 1 instance read/write + 1 persistent write (new) or rw (existing). + #[test] + fn estimate_mint_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let user = Address::generate(&env); + + // First mint — creates new persistent balance entry + client.mint(&user, &1_000_i128); + assert_eq!(client.balance(&user), 1_000_i128); + assert_eq!(client.total_supply(), 1_000_i128); + + // Second mint to same address — updates existing persistent entry + client.mint(&user, &500_i128); + assert_eq!(client.balance(&user), 1_500_i128); + assert_eq!(client.total_supply(), 1_500_i128); + + println!( + "[storage_cost] mint: \ + 1st call → 1 instance rw + 1 persistent write; \ + subsequent → 1 instance rw + 1 persistent rw" + ); + } + + // ── burn ───────────────────────────────────────────────────────────────── + + /// `burn`: + /// reads — balance(persistent), TotalBurned(instance) + /// writes — balance(persistent), TotalBurned(instance) + /// + /// Ledger entry ops: 1 instance rw + 1 persistent rw. + #[test] + fn estimate_burn_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let user = Address::generate(&env); + client.mint(&user, &5_000_i128); + + client.burn(&user, &2_000_i128); + assert_eq!(client.balance(&user), 3_000_i128); + assert_eq!(client.total_supply(), 3_000_i128); + + println!( + "[storage_cost] burn: 1 instance rw (TotalBurned) + 1 persistent rw (balance)" + ); + } + + // ── transfer ───────────────────────────────────────────────────────────── + + /// `transfer`: + /// reads — balance(from, persistent), balance(to, persistent) + /// writes — balance(from, persistent), balance(to, persistent) + /// + /// Ledger entry ops: 2 persistent rw (from + to balances). + /// Note: no instance storage is touched. + #[test] + fn estimate_transfer_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let from = Address::generate(&env); + let to = Address::generate(&env); + client.mint(&from, &2_000_i128); + + client.transfer(&from, &to, &1_000_i128); + assert_eq!(client.balance(&from), 1_000_i128); + assert_eq!(client.balance(&to), 1_000_i128); + + println!( + "[storage_cost] transfer: 2 persistent rw (from-balance + to-balance)" + ); + } + + /// `transfer` to self: `move_balance` short-circuits when `from == to`, + /// so no storage is written (only reads occur for the pause/retire checks). + #[test] + fn estimate_transfer_to_self_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let user = Address::generate(&env); + client.mint(&user, &1_000_i128); + + client.transfer(&user, &user, &500_i128); + assert_eq!(client.balance(&user), 1_000_i128); // unchanged + + println!( + "[storage_cost] transfer (self): early return — 0 persistent writes \ + (only Paused/Retired instance reads)" + ); + } + + // ── approve / transfer_from ─────────────────────────────────────────────── + + /// `approve`: + /// writes — Allowance(from, spender, persistent) + /// + /// `transfer_from`: + /// reads — Allowance(persistent), balance(from, persistent), balance(to, persistent) + /// writes — Allowance(persistent), balance(from, persistent), balance(to, persistent) + /// + /// Combined ledger entry ops: 1 persistent write (approve) + 3-4 persistent ops (transfer_from). + #[test] + fn estimate_approve_transfer_from_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let owner = Address::generate(&env); + let spender = Address::generate(&env); + let recipient = Address::generate(&env); + client.mint(&owner, &3_000_i128); + + // approve: 1 persistent write (Allowance) + client.approve(&owner, &spender, &2_000_i128, &9_999_u32); + assert_eq!(client.allowance(&owner, &spender), 2_000_i128); + + // transfer_from: 1 persistent rw (Allowance) + 2 persistent rw (balances) + client.transfer_from(&spender, &owner, &recipient, &1_500_i128); + assert_eq!(client.balance(&owner), 1_500_i128); + assert_eq!(client.balance(&recipient), 1_500_i128); + assert_eq!(client.allowance(&owner, &spender), 500_i128); + + println!( + "[storage_cost] approve: 1 persistent write; \ + transfer_from: 3 persistent rw (Allowance + 2x balance)" + ); + } + + // ── burn_from ───────────────────────────────────────────────────────────── + + /// `burn_from`: + /// reads — Allowance(persistent), balance(from, persistent), TotalBurned(instance) + /// writes — Allowance(persistent), balance(from, persistent), TotalBurned(instance) + /// + /// Ledger entry ops: 2 persistent rw + 1 instance rw. + #[test] + fn estimate_burn_from_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let owner = Address::generate(&env); + let spender = Address::generate(&env); + client.mint(&owner, &1_000_i128); + client.approve(&owner, &spender, &600_i128, &9_999_u32); + + client.burn_from(&spender, &owner, &400_i128); + assert_eq!(client.balance(&owner), 600_i128); + assert_eq!(client.total_supply(), 600_i128); + assert_eq!(client.allowance(&owner, &spender), 200_i128); + + println!( + "[storage_cost] burn_from: 2 persistent rw (Allowance + balance) \ + + 1 instance rw (TotalBurned)" + ); + } + + // ── set_minter ──────────────────────────────────────────────────────────── + + /// `set_minter`: + /// reads — Admin(instance) + /// writes — Minter(instance) + /// + /// Ledger entry ops: 1 instance read + 1 instance write + /// (both instance keys share a single ledger entry, so this is 1 entry touched). + #[test] + fn estimate_set_minter_storage_ops() { + let (env, client, admin, _minter) = setup(); + let new_minter = Address::generate(&env); + + client.set_minter(&admin, &new_minter); + + println!( + "[storage_cost] set_minter: 1 instance read (Admin) + 1 instance write (Minter) \ + = 1 instance ledger entry touched" + ); + } + + // ── total_supply / balance ──────────────────────────────────────────────── + + /// `total_supply`: + /// reads — TotalMinted(instance), TotalBurned(instance) + /// + /// `balance`: + /// reads — balance(persistent) + /// + /// Both are read-only; no writes. + #[test] + fn estimate_read_only_ops() { + let (env, client, _admin, _minter) = setup(); + let user = Address::generate(&env); + client.mint(&user, &1_000_i128); + client.burn(&user, &200_i128); + + let _ = client.total_supply(); // 2 instance reads + let _ = client.balance(&user); // 1 persistent read + + println!( + "[storage_cost] total_supply: 2 instance reads (no writes); \ + balance: 1 persistent read (no writes)" + ); + } + + // ── retire ──────────────────────────────────────────────────────────────── + + /// `retire`: + /// reads — Retired(persistent), balance(persistent), TotalBurned(instance) + /// writes — balance(persistent), Retired(persistent) [if full balance retired], TotalBurned(instance) + /// + /// Ledger entry ops: 2-3 persistent ops + 1 instance rw. + #[test] + fn estimate_retire_storage_ops() { + let (env, client, _admin, _minter) = setup(); + let user = Address::generate(&env); + client.mint(&user, &2_000_i128); + + let reason = soroban_sdk::String::from_str(&env, "REC compliance"); + client.retire(&user, &2_000_i128, &reason); + assert_eq!(client.balance(&user), 0_i128); + assert_eq!(client.total_supply(), 0_i128); + + println!( + "[storage_cost] retire (full balance): \ + 3 persistent ops (Retired read, balance rw, Retired write) \ + + 1 instance rw (TotalBurned)" + ); + } + + // ── summary ─────────────────────────────────────────────────────────────── + + /// Prints a full storage cost summary for all energy_token methods. + /// Run with `-- --nocapture` to see output. + #[test] + fn storage_cost_summary() { + println!( + "\n\ + ╔══════════════════════════════════════════════════════════════════╗\n\ + ║ Storage Cost Summary — energy_token (issue #564) ║\n\ + ╠══════════════════╦══════════════╦═════════════════════════════════╣\n\ + ║ Method ║ Instance ops ║ Persistent ops ║\n\ + ╠══════════════════╬══════════════╬═════════════════════════════════╣\n\ + ║ initialize ║ 5 writes ║ — ║\n\ + ║ mint (new addr) ║ 1 rw ║ 1 write (new balance entry) ║\n\ + ║ mint (existing) ║ 1 rw ║ 1 rw (existing balance) ║\n\ + ║ burn ║ 1 rw ║ 1 rw (balance) ║\n\ + ║ transfer ║ — ║ 2 rw (from + to balances) ║\n\ + ║ transfer (self) ║ — ║ — (early return) ║\n\ + ║ approve ║ — ║ 1 write (Allowance) ║\n\ + ║ transfer_from ║ — ║ 3 rw (Allowance + 2 balances) ║\n\ + ║ burn_from ║ 1 rw ║ 2 rw (Allowance + balance) ║\n\ + ║ set_minter ║ 1 r + 1 w ║ — ║\n\ + ║ total_supply ║ 2 reads ║ — ║\n\ + ║ balance ║ — ║ 1 read ║\n\ + ║ retire (partial) ║ 1 rw ║ 2 rw (Retired read + balance) ║\n\ + ║ retire (full) ║ 1 rw ║ 3 ops (+ Retired write) ║\n\ + ╚══════════════════╩══════════════╩═════════════════════════════════╝\n\ + \n\ + Legend: rw = read then write; r = read only; w = write only\n\ + Instance ops share ONE ledger entry (the contract instance blob).\n\ + Each persistent op is a SEPARATE ledger entry." + ); + } +} diff --git a/apps/web/messages/de.json b/apps/web/messages/de.json index 6b56a3e..ca8046b 100644 --- a/apps/web/messages/de.json +++ b/apps/web/messages/de.json @@ -73,5 +73,16 @@ "daysInvalid": "Geben Sie eine Zahl zwischen 1 und 30 ein." } } + }, + "walletGate": { + "title": "Wallet erforderlich", + "description": "Verbinden Sie Ihre Freighter-Wallet, um auf diese Seite zuzugreifen.", + "connect": "Wallet verbinden", + "reconnect": "Wallet erneut verbinden", + "connecting": "Verbinden…", + "connectError": "Verbindung zur Wallet nicht möglich. Bitte erneut versuchen.", + "disconnectedTitle": "Wallet getrennt", + "disconnectedDescription": "Ihre Wallet-Sitzung ist abgelaufen. Verbinden Sie sich erneut, um fortzufahren.", + "disconnectedHint": "Stellen Sie sicher, dass Ihre Freighter-Erweiterung entsperrt ist und das richtige Konto ausgewählt ist." } } diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 2f4ac61..032b880 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -78,6 +78,12 @@ "walletGate": { "title": "Wallet required", "description": "Connect your Freighter wallet to access this page.", - "connect": "Connect wallet" + "connect": "Connect wallet", + "reconnect": "Reconnect wallet", + "connecting": "Connecting…", + "connectError": "Could not connect to wallet. Please try again.", + "disconnectedTitle": "Wallet disconnected", + "disconnectedDescription": "Your wallet session has ended. Reconnect to continue using wallet-dependent features.", + "disconnectedHint": "Make sure your Freighter extension is unlocked and the correct account is selected." } } diff --git a/apps/web/messages/es.json b/apps/web/messages/es.json index c3fb685..2064c6a 100644 --- a/apps/web/messages/es.json +++ b/apps/web/messages/es.json @@ -73,5 +73,16 @@ "daysInvalid": "Ingrese un número entre 1 y 30." } } + }, + "walletGate": { + "title": "Billetera requerida", + "description": "Conecta tu billetera Freighter para acceder a esta página.", + "connect": "Conectar billetera", + "reconnect": "Reconectar billetera", + "connecting": "Conectando…", + "connectError": "No se pudo conectar a la billetera. Inténtalo de nuevo.", + "disconnectedTitle": "Billetera desconectada", + "disconnectedDescription": "Tu sesión de billetera ha expirado. Vuelve a conectarte para continuar.", + "disconnectedHint": "Asegúrate de que tu extensión Freighter esté desbloqueada y la cuenta correcta esté seleccionada." } } diff --git a/apps/web/messages/fr.json b/apps/web/messages/fr.json index 0b117f5..54e1bb3 100644 --- a/apps/web/messages/fr.json +++ b/apps/web/messages/fr.json @@ -73,5 +73,16 @@ "daysInvalid": "Entrez un nombre entre 1 et 30." } } + }, + "walletGate": { + "title": "Portefeuille requis", + "description": "Connectez votre portefeuille Freighter pour accéder à cette page.", + "connect": "Connecter le portefeuille", + "reconnect": "Reconnecter le portefeuille", + "connecting": "Connexion…", + "connectError": "Impossible de se connecter au portefeuille. Veuillez réessayer.", + "disconnectedTitle": "Portefeuille déconnecté", + "disconnectedDescription": "Votre session de portefeuille a expiré. Reconnectez-vous pour continuer.", + "disconnectedHint": "Assurez-vous que votre extension Freighter est déverrouillée et que le bon compte est sélectionné." } } diff --git a/apps/web/package.json b/apps/web/package.json index fb61846..68869a9 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,7 +14,7 @@ "mutation": "stryker run" }, "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.1073.0", + "@aws-sdk/client-secrets-manager": "^3.1075.0", "@noble/ed25519": "2.3.0", "@opentelemetry/exporter-trace-otlp-http": "^0.219.0", "@opentelemetry/instrumentation-fetch": "^0.219.0", @@ -28,15 +28,15 @@ "@stellar/stellar-sdk": "^13.1.0", "@supabase/supabase-js": "^2.108.2", "@t3-oss/env-nextjs": "0.13.11", - "@tanstack/react-query": "^5.101.0", + "@tanstack/react-query": "^5.101.2", "@vercel/analytics": "^1.4.0", "@vercel/speed-insights": "^1.1.0", - "bullmq": "5.79.1", + "bullmq": "5.79.2", "clsx": "^2.1.1", "ioredis": "5.11.1", "lucide-react": "^0.577.0", "next": "15.5.19", - "next-intl": "^4.13.0", + "next-intl": "^4.13.1", "next-themes": "^0.4.4", "react": "^19.2.7", "react-dom": "^19.2.7", @@ -45,10 +45,10 @@ "zod": "^3.24.1" }, "devDependencies": { - "@axe-core/playwright": "^4.11.3", + "@axe-core/playwright": "^4.12.1", "@eslint/eslintrc": "^3.3.5", "@noble/ed25519": "^2.3.0", - "@playwright/test": "^1.61.0", + "@playwright/test": "^1.61.1", "@testing-library/react": "^16.1.0", "@types/node": "^22.20.0", "@types/react": "^19.2.17", @@ -59,7 +59,7 @@ "eslint-config-next": "15.5.19", "jsdom": "^25.0.1", "prettier-plugin-tailwindcss": "^0.8.0", - "tailwindcss": "^4.0.0", + "tailwindcss": "^4.3.2", "typescript": "^5.6.3", "vitest": "^2.1.8" } diff --git a/apps/web/src/__tests__/components/__snapshots__/snapshot.test.tsx.snap b/apps/web/src/__tests__/components/__snapshots__/snapshot.test.tsx.snap index a21eb9a..198b065 100644 --- a/apps/web/src/__tests__/components/__snapshots__/snapshot.test.tsx.snap +++ b/apps/web/src/__tests__/components/__snapshots__/snapshot.test.tsx.snap @@ -3,6 +3,7 @@ exports[`Copy components snapshots > CopyButton renders correctly 1`] = ` - - -
- {analyticsLoading ? : ( - - - - - - - - - - )} -
+ {analyticsLoading ? : ( + + + + + + + + + + )} + + + {/* Issuance vs Retirement */} +
-
-
-

Certificates activity

-

Issued vs retired trends

+
+
+
+

Certificates activity

+

Issued vs retired trends

+
+
+ Certificate activity time grouping + {(['day', 'month'] as const).map((g) => ( + + ))} +
-
- {(['day', 'month'] as const).map((g) => ( - - ))} -
-
-
- {analyticsLoading ? : ( - - - - - - - - - - - - )} -
+

+ {describeCertificateActivity(analytics?.trends, range, granularity)} +

+
+ {analyticsLoading ? : ( + + + + + + + ( + + )} + /> + + + + + )} +
+
+ {/* Per-Meter Breakdown */} @@ -379,10 +457,15 @@ export default function DashboardPage() { {m.certs_generated.toLocaleString()}
-
-
+ diff --git a/apps/web/src/app/governance/page.tsx b/apps/web/src/app/governance/page.tsx index 2345193..0fada59 100644 --- a/apps/web/src/app/governance/page.tsx +++ b/apps/web/src/app/governance/page.tsx @@ -1,9 +1,11 @@ 'use client' +// . import { useState } from 'react' import { Vote, Plus, Clock, CheckCircle, XCircle, Minus, ChevronDown, ChevronUp } from 'lucide-react' import { useWallet } from '@/hooks/useWallet' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' +import { ProposalListSkeleton } from '@/components/skeleton' // ── Types ────────────────────────────────────────────────────────────────────── @@ -91,16 +93,32 @@ function TallyBar({ tally }: { tally: Tally }) { const abstainPct = pct(tally.abstain, total) return (
-
-
-
-
-
-
- {forPct}% For ({tally.for}) - {againstPct}% Against ({tally.against}) - {abstainPct}% Abstain ({tally.abstain}) +
+ )} + {submitError && ( +
+ {submitError} +
+ )}
void }) { /> - +