From 5e7e36ee7e58a63dcf82503e8c7b9764fcccfba5 Mon Sep 17 00:00:00 2001 From: OthmanImam Date: Sat, 21 Feb 2026 22:18:36 +0100 Subject: [PATCH 1/5] Implemented Advance Decentralized --- Cargo.toml | 2 + contracts/IDENTITY_CREDENTIAL.md | 23 ++++++ contracts/credential_registry/Cargo.toml | 22 ++++++ contracts/credential_registry/src/lib.rs | 72 ++++++++++++++++++ contracts/identity_registry/Cargo.toml | 22 ++++++ contracts/identity_registry/src/lib.rs | 93 ++++++++++++++++++++++++ 6 files changed, 234 insertions(+) create mode 100644 contracts/IDENTITY_CREDENTIAL.md create mode 100644 contracts/credential_registry/Cargo.toml create mode 100644 contracts/credential_registry/src/lib.rs create mode 100644 contracts/identity_registry/Cargo.toml create mode 100644 contracts/identity_registry/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index e371d29..cfa13fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ members = [ "contracts/governance", "contracts/insurance", "contracts/teachlink", + "contracts/identity_registry", + "contracts/credential_registry", ] [workspace.package] diff --git a/contracts/IDENTITY_CREDENTIAL.md b/contracts/IDENTITY_CREDENTIAL.md new file mode 100644 index 0000000..117f0fa --- /dev/null +++ b/contracts/IDENTITY_CREDENTIAL.md @@ -0,0 +1,23 @@ +**Identity & Credential Contracts (Soroban)** + +Overview +- `identity-registry`: on-chain DID registry. Stores DID -> controller, auth methods, recovery address. +- `credential-registry`: on-chain credential index. Stores credential hash -> (issuer DID, subject DID, metadata pointer, expires_at, status). + +Key on-chain guarantees +- Deterministic verification can check presence and status of a credential on-chain. +- Full VC JSON and ZK proofs remain off-chain; only hashes/roots and status bits stored on-chain. + +Next steps / integration notes +- Wire `credential-registry` to call `identity-registry` for authoritative issuer controller checks. +- Add Merkle/bitmap-based revocation root support for efficient revocation proofs. +- Implement cross-contract calls and auth to allow DID controllers (not raw addresses) to issue/revoke. +- Add off-chain ZK proof verifier support: store verification circuits' commitment roots on-chain and provide helper APIs for verifiers. +- Marketplace, federation, selective-disclosure circuits, and biometric-binding are implemented off-chain; contracts store anchors/roots. + +Files added +- `contracts/identity_registry` — Cargo + src/lib.rs +- `contracts/credential_registry` — Cargo + src/lib.rs + +Testing & build +- Use the workspace's soroban toolchain and existing patterns (see other `contracts/*` crates) to build and test. diff --git a/contracts/credential_registry/Cargo.toml b/contracts/credential_registry/Cargo.toml new file mode 100644 index 0000000..bce73ef --- /dev/null +++ b/contracts/credential_registry/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "credential-registry" +version = "0.1.0" +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk.workspace = true + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[lints] +workspace = true + diff --git a/contracts/credential_registry/src/lib.rs b/contracts/credential_registry/src/lib.rs new file mode 100644 index 0000000..ee1736d --- /dev/null +++ b/contracts/credential_registry/src/lib.rs @@ -0,0 +1,72 @@ + +#![no_std] + + +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Bytes, BytesN}; + +#[contract] +pub struct CredentialRegistryContract; + +#[derive(Clone)] +pub enum CredentialStatus { + Active, + Revoked, + Expired, +} + +#[contractimpl] +impl CredentialRegistryContract { + // Issue a credential by storing its hash and metadata pointer. + // `credential_hash` should be a deterministic hash (e.g., SHA-256) of the full VC JSON. + pub fn issue_credential( + env: &Env, + credential_hash: BytesN<32>, + issuer: Address, + issuer_did: Bytes, + subject_did: Bytes, + metadata_ptr: Bytes, + expires_at: i128, + ) { + issuer.require_auth(); + let key = (symbol_short!("cred"), credential_hash.clone()); + assert!(!env.storage().persistent().has(&key), "credential already exists"); + let record: (Bytes, Bytes, Bytes, i128, i32) = (issuer_did.clone(), subject_did.clone(), metadata_ptr.clone(), expires_at, 0i32); + env.storage().persistent().set(&key, &record); + env.events().publish((symbol_short!("crediss"),), (credential_hash, issuer_did, subject_did, metadata_ptr, expires_at)); + } + + // Revoke a credential. Caller must be issuer (signed address) + pub fn revoke_credential(env: &Env, credential_hash: BytesN<32>, issuer: Address) { + issuer.require_auth(); + let key = (symbol_short!("cred"), credential_hash.clone()); + let opt: Option<(Bytes, Bytes, Bytes, i128, i32)> = env.storage().persistent().get(&key); + match opt { + Some((issuer_did, subject_did, metadata_ptr, expires_at, _status)) => { + let record: (Bytes, Bytes, Bytes, i128, i32) = (issuer_did.clone(), subject_did.clone(), metadata_ptr.clone(), expires_at, 1i32); + env.storage().persistent().set(&key, &record); + env.events().publish((symbol_short!("credrev"),), (credential_hash, issuer_did, subject_did)); + } + None => panic!("credential not found"), + } + } + + // Get credential record: returns (issuer_did, subject_did, metadata_ptr, expires_at, status) + pub fn get_credential(env: &Env, credential_hash: BytesN<32>) -> Option<(Bytes, Bytes, Bytes, i128, i32)> { + let key = (symbol_short!("cred"), credential_hash.clone()); + env.storage().persistent().get(&key) + } + + // Check if credential is active (not revoked and not expired) + pub fn is_active(env: &Env, credential_hash: BytesN<32>, now_ts: i128) -> bool { + match Self::get_credential(env, credential_hash.clone()) { + Some((_issuer, _subject, _meta, expires_at, status)) => { + if status == 1 { return false; } + if expires_at > 0 && now_ts > expires_at { return false; } + true + } + None => false, + } + } +} + +fn main() {} diff --git a/contracts/identity_registry/Cargo.toml b/contracts/identity_registry/Cargo.toml new file mode 100644 index 0000000..e90a9b5 --- /dev/null +++ b/contracts/identity_registry/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "identity-registry" +version = "0.1.0" +edition.workspace = true +repository.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk.workspace = true + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[lints] +workspace = true + diff --git a/contracts/identity_registry/src/lib.rs b/contracts/identity_registry/src/lib.rs new file mode 100644 index 0000000..967a5a8 --- /dev/null +++ b/contracts/identity_registry/src/lib.rs @@ -0,0 +1,93 @@ +#![no_std] + +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Bytes, BytesN}; + +#[contract] +pub struct IdentityRegistryContract; + +#[contractimpl] +impl IdentityRegistryContract { + // Create a new DID mapping to a controller address. + pub fn create_did(env: &Env, identity_id: BytesN<32>, controller: Address) { + controller.require_auth(); + let key = (symbol_short!("didctl"), identity_id.clone()); + assert!(!env.storage().persistent().has(&key), "DID already exists"); + env.storage().persistent().set(&key, &controller); + env.events().publish((symbol_short!("didcrt"),), (identity_id, controller)); + } + + // Get controller for a DID + pub fn get_controller(env: &Env, identity_id: BytesN<32>) -> Option
{ + let key = (symbol_short!("didctl"), identity_id.clone()); + env.storage().persistent().get(&key) + } + + // Update controller. Caller must pass the current controller and sign the call. + pub fn set_controller(env: &Env, identity_id: BytesN<32>, current_controller: Address, new_controller: Address) { + current_controller.require_auth(); + let key = (symbol_short!("did_ctrl"), identity_id.clone()); + let opt: Option
= env.storage().persistent().get(&key); + match opt { + Some(stored) => { + assert!(stored == current_controller, "only controller can change controller"); + env.storage().persistent().set(&key, &new_controller); + env.events().publish((symbol_short!("didchg"),), (identity_id, new_controller)); + } + None => panic!("DID not found"), + } + } + + // Add or update an authentication method (e.g., key, service) for a DID + pub fn set_auth_method(env: &Env, identity_id: BytesN<32>, controller: Address, method_id: Bytes, public_key: Bytes) { + controller.require_auth(); + let ctrl_key = (symbol_short!("didctl"), identity_id.clone()); + let current: Option
= env.storage().persistent().get(&ctrl_key); + assert!(current.is_some(), "DID not found"); + assert!(current.unwrap() == controller, "only controller can set auth methods"); + let key = (symbol_short!("auth"), identity_id.clone(), method_id.clone()); + env.storage().persistent().set(&key, &public_key); + env.events().publish((symbol_short!("authset"),), (identity_id, method_id, public_key)); + } + + // Remove an auth method + pub fn remove_auth_method(env: &Env, identity_id: BytesN<32>, controller: Address, method_id: Bytes) { + controller.require_auth(); + let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); + let current: Option
= env.storage().persistent().get(&ctrl_key); + assert!(current.is_some(), "DID not found"); + assert!(current.unwrap() == controller, "only controller can remove auth methods"); + let key = (symbol_short!("auth"), identity_id.clone(), method_id.clone()); + env.storage().persistent().remove(&key); + env.events().publish((symbol_short!("authrem"),), (identity_id, method_id)); + } + + // Set a recovery address that may be used to recover control of the DID + pub fn set_recovery(env: &Env, identity_id: BytesN<32>, controller: Address, recovery: Address) { + controller.require_auth(); + let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); + let current: Option
= env.storage().persistent().get(&ctrl_key); + assert!(current.is_some(), "DID not found"); + assert!(current.unwrap() == controller, "only controller can set recovery"); + let key = (symbol_short!("recovery"), identity_id.clone()); + env.storage().persistent().set(&key, &recovery); + env.events().publish((symbol_short!("recovery"),), (identity_id, recovery)); + } + + // Recover controller using the configured recovery address + pub fn recover(env: &Env, identity_id: BytesN<32>, recovery: Address, new_controller: Address) { + recovery.require_auth(); + let rec_key = (symbol_short!("recovery"), identity_id.clone()); + let rec_opt: Option
= env.storage().persistent().get(&rec_key); + match rec_opt { + Some(recovery_addr) => { + assert!(recovery_addr == recovery, "only recovery address can perform recovery"); + let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); + env.storage().persistent().set(&ctrl_key, &new_controller); + env.events().publish((symbol_short!("didrec"),), (identity_id, new_controller)); + } + None => panic!("no recovery configured for DID"), + } + } +} + +fn main() {} From 06eb41593a23579d3e1e22e9a42c889635b57dd8 Mon Sep 17 00:00:00 2001 From: OthmanImam Date: Sat, 21 Feb 2026 22:19:08 +0100 Subject: [PATCH 2/5] run format --- contracts/credential_registry/src/lib.rs | 54 ++++++++++++--- contracts/identity_registry/src/lib.rs | 88 +++++++++++++++++++----- 2 files changed, 113 insertions(+), 29 deletions(-) diff --git a/contracts/credential_registry/src/lib.rs b/contracts/credential_registry/src/lib.rs index ee1736d..8b69510 100644 --- a/contracts/credential_registry/src/lib.rs +++ b/contracts/credential_registry/src/lib.rs @@ -1,8 +1,6 @@ - #![no_std] - -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Bytes, BytesN}; +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Bytes, BytesN, Env}; #[contract] pub struct CredentialRegistryContract; @@ -29,10 +27,28 @@ impl CredentialRegistryContract { ) { issuer.require_auth(); let key = (symbol_short!("cred"), credential_hash.clone()); - assert!(!env.storage().persistent().has(&key), "credential already exists"); - let record: (Bytes, Bytes, Bytes, i128, i32) = (issuer_did.clone(), subject_did.clone(), metadata_ptr.clone(), expires_at, 0i32); + assert!( + !env.storage().persistent().has(&key), + "credential already exists" + ); + let record: (Bytes, Bytes, Bytes, i128, i32) = ( + issuer_did.clone(), + subject_did.clone(), + metadata_ptr.clone(), + expires_at, + 0i32, + ); env.storage().persistent().set(&key, &record); - env.events().publish((symbol_short!("crediss"),), (credential_hash, issuer_did, subject_did, metadata_ptr, expires_at)); + env.events().publish( + (symbol_short!("crediss"),), + ( + credential_hash, + issuer_did, + subject_did, + metadata_ptr, + expires_at, + ), + ); } // Revoke a credential. Caller must be issuer (signed address) @@ -42,16 +58,28 @@ impl CredentialRegistryContract { let opt: Option<(Bytes, Bytes, Bytes, i128, i32)> = env.storage().persistent().get(&key); match opt { Some((issuer_did, subject_did, metadata_ptr, expires_at, _status)) => { - let record: (Bytes, Bytes, Bytes, i128, i32) = (issuer_did.clone(), subject_did.clone(), metadata_ptr.clone(), expires_at, 1i32); + let record: (Bytes, Bytes, Bytes, i128, i32) = ( + issuer_did.clone(), + subject_did.clone(), + metadata_ptr.clone(), + expires_at, + 1i32, + ); env.storage().persistent().set(&key, &record); - env.events().publish((symbol_short!("credrev"),), (credential_hash, issuer_did, subject_did)); + env.events().publish( + (symbol_short!("credrev"),), + (credential_hash, issuer_did, subject_did), + ); } None => panic!("credential not found"), } } // Get credential record: returns (issuer_did, subject_did, metadata_ptr, expires_at, status) - pub fn get_credential(env: &Env, credential_hash: BytesN<32>) -> Option<(Bytes, Bytes, Bytes, i128, i32)> { + pub fn get_credential( + env: &Env, + credential_hash: BytesN<32>, + ) -> Option<(Bytes, Bytes, Bytes, i128, i32)> { let key = (symbol_short!("cred"), credential_hash.clone()); env.storage().persistent().get(&key) } @@ -60,8 +88,12 @@ impl CredentialRegistryContract { pub fn is_active(env: &Env, credential_hash: BytesN<32>, now_ts: i128) -> bool { match Self::get_credential(env, credential_hash.clone()) { Some((_issuer, _subject, _meta, expires_at, status)) => { - if status == 1 { return false; } - if expires_at > 0 && now_ts > expires_at { return false; } + if status == 1 { + return false; + } + if expires_at > 0 && now_ts > expires_at { + return false; + } true } None => false, diff --git a/contracts/identity_registry/src/lib.rs b/contracts/identity_registry/src/lib.rs index 967a5a8..9fd5934 100644 --- a/contracts/identity_registry/src/lib.rs +++ b/contracts/identity_registry/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Bytes, BytesN}; +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Bytes, BytesN, Env}; #[contract] pub struct IdentityRegistryContract; @@ -13,7 +13,8 @@ impl IdentityRegistryContract { let key = (symbol_short!("didctl"), identity_id.clone()); assert!(!env.storage().persistent().has(&key), "DID already exists"); env.storage().persistent().set(&key, &controller); - env.events().publish((symbol_short!("didcrt"),), (identity_id, controller)); + env.events() + .publish((symbol_short!("didcrt"),), (identity_id, controller)); } // Get controller for a DID @@ -23,54 +24,101 @@ impl IdentityRegistryContract { } // Update controller. Caller must pass the current controller and sign the call. - pub fn set_controller(env: &Env, identity_id: BytesN<32>, current_controller: Address, new_controller: Address) { + pub fn set_controller( + env: &Env, + identity_id: BytesN<32>, + current_controller: Address, + new_controller: Address, + ) { current_controller.require_auth(); let key = (symbol_short!("did_ctrl"), identity_id.clone()); let opt: Option
= env.storage().persistent().get(&key); match opt { Some(stored) => { - assert!(stored == current_controller, "only controller can change controller"); + assert!( + stored == current_controller, + "only controller can change controller" + ); env.storage().persistent().set(&key, &new_controller); - env.events().publish((symbol_short!("didchg"),), (identity_id, new_controller)); + env.events() + .publish((symbol_short!("didchg"),), (identity_id, new_controller)); } None => panic!("DID not found"), } } // Add or update an authentication method (e.g., key, service) for a DID - pub fn set_auth_method(env: &Env, identity_id: BytesN<32>, controller: Address, method_id: Bytes, public_key: Bytes) { + pub fn set_auth_method( + env: &Env, + identity_id: BytesN<32>, + controller: Address, + method_id: Bytes, + public_key: Bytes, + ) { controller.require_auth(); let ctrl_key = (symbol_short!("didctl"), identity_id.clone()); let current: Option
= env.storage().persistent().get(&ctrl_key); assert!(current.is_some(), "DID not found"); - assert!(current.unwrap() == controller, "only controller can set auth methods"); - let key = (symbol_short!("auth"), identity_id.clone(), method_id.clone()); + assert!( + current.unwrap() == controller, + "only controller can set auth methods" + ); + let key = ( + symbol_short!("auth"), + identity_id.clone(), + method_id.clone(), + ); env.storage().persistent().set(&key, &public_key); - env.events().publish((symbol_short!("authset"),), (identity_id, method_id, public_key)); + env.events().publish( + (symbol_short!("authset"),), + (identity_id, method_id, public_key), + ); } // Remove an auth method - pub fn remove_auth_method(env: &Env, identity_id: BytesN<32>, controller: Address, method_id: Bytes) { + pub fn remove_auth_method( + env: &Env, + identity_id: BytesN<32>, + controller: Address, + method_id: Bytes, + ) { controller.require_auth(); let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); let current: Option
= env.storage().persistent().get(&ctrl_key); assert!(current.is_some(), "DID not found"); - assert!(current.unwrap() == controller, "only controller can remove auth methods"); - let key = (symbol_short!("auth"), identity_id.clone(), method_id.clone()); + assert!( + current.unwrap() == controller, + "only controller can remove auth methods" + ); + let key = ( + symbol_short!("auth"), + identity_id.clone(), + method_id.clone(), + ); env.storage().persistent().remove(&key); - env.events().publish((symbol_short!("authrem"),), (identity_id, method_id)); + env.events() + .publish((symbol_short!("authrem"),), (identity_id, method_id)); } // Set a recovery address that may be used to recover control of the DID - pub fn set_recovery(env: &Env, identity_id: BytesN<32>, controller: Address, recovery: Address) { + pub fn set_recovery( + env: &Env, + identity_id: BytesN<32>, + controller: Address, + recovery: Address, + ) { controller.require_auth(); let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); let current: Option
= env.storage().persistent().get(&ctrl_key); assert!(current.is_some(), "DID not found"); - assert!(current.unwrap() == controller, "only controller can set recovery"); + assert!( + current.unwrap() == controller, + "only controller can set recovery" + ); let key = (symbol_short!("recovery"), identity_id.clone()); env.storage().persistent().set(&key, &recovery); - env.events().publish((symbol_short!("recovery"),), (identity_id, recovery)); + env.events() + .publish((symbol_short!("recovery"),), (identity_id, recovery)); } // Recover controller using the configured recovery address @@ -80,10 +128,14 @@ impl IdentityRegistryContract { let rec_opt: Option
= env.storage().persistent().get(&rec_key); match rec_opt { Some(recovery_addr) => { - assert!(recovery_addr == recovery, "only recovery address can perform recovery"); + assert!( + recovery_addr == recovery, + "only recovery address can perform recovery" + ); let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); env.storage().persistent().set(&ctrl_key, &new_controller); - env.events().publish((symbol_short!("didrec"),), (identity_id, new_controller)); + env.events() + .publish((symbol_short!("didrec"),), (identity_id, new_controller)); } None => panic!("no recovery configured for DID"), } From ab3f81917d35d2bc724e1d99356f1f2cda57f10c Mon Sep 17 00:00:00 2001 From: OthmanImam Date: Sun, 22 Feb 2026 18:46:29 +0100 Subject: [PATCH 3/5] updated --- contracts/credential_registry/src/lib.rs | 45 +- .../test_address_validation.1.json | 61 ++ .../test_bridge_completion_validation.1.json | 61 ++ .../test_bridge_validation_edge_cases.1.json | 86 ++ .../test_cross_chain_validation.1.json | 111 +++ .../test_escrow_dispute_refund.1.json | 165 +++- .../test_escrow_release_flow.1.json | 256 +++++- .../test_escrow_validation_edge_cases.1.json | 86 ++ ...st_professional_arbitration_picking.1.json | 810 ++++++++++++++++++ .../test_rewards_validation_edge_cases.1.json | 86 ++ 10 files changed, 1738 insertions(+), 29 deletions(-) create mode 100644 contracts/teachlink/test_snapshots/test_address_validation.1.json create mode 100644 contracts/teachlink/test_snapshots/test_bridge_completion_validation.1.json create mode 100644 contracts/teachlink/test_snapshots/test_bridge_validation_edge_cases.1.json create mode 100644 contracts/teachlink/test_snapshots/test_cross_chain_validation.1.json create mode 100644 contracts/teachlink/test_snapshots/test_escrow_validation_edge_cases.1.json create mode 100644 contracts/teachlink/test_snapshots/test_professional_arbitration_picking.1.json create mode 100644 contracts/teachlink/test_snapshots/test_rewards_validation_edge_cases.1.json diff --git a/contracts/credential_registry/src/lib.rs b/contracts/credential_registry/src/lib.rs index 8b69510..21a1fd9 100644 --- a/contracts/credential_registry/src/lib.rs +++ b/contracts/credential_registry/src/lib.rs @@ -1,7 +1,24 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Bytes, BytesN, Env}; +use soroban_sdk::{contract, contractimpl, contractevent, symbol_short, Address, Bytes, BytesN, Env}; +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Crediss { + pub credential_hash: BytesN<32>, + pub issuer_did: Bytes, + pub subject_did: Bytes, + pub metadata_ptr: Bytes, + pub expires_at: i128, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Credrev { + pub credential_hash: BytesN<32>, + pub issuer_did: Bytes, + pub subject_did: Bytes, +} #[contract] pub struct CredentialRegistryContract; @@ -39,16 +56,13 @@ impl CredentialRegistryContract { 0i32, ); env.storage().persistent().set(&key, &record); - env.events().publish( - (symbol_short!("crediss"),), - ( - credential_hash, - issuer_did, - subject_did, - metadata_ptr, - expires_at, - ), - ); + Crediss { + credential_hash, + issuer_did, + subject_did, + metadata_ptr, + expires_at, + }.publish(env); } // Revoke a credential. Caller must be issuer (signed address) @@ -66,10 +80,11 @@ impl CredentialRegistryContract { 1i32, ); env.storage().persistent().set(&key, &record); - env.events().publish( - (symbol_short!("credrev"),), - (credential_hash, issuer_did, subject_did), - ); + Credrev { + credential_hash, + issuer_did, + subject_did, + }.publish(env); } None => panic!("credential not found"), } diff --git a/contracts/teachlink/test_snapshots/test_address_validation.1.json b/contracts/teachlink/test_snapshots/test_address_validation.1.json new file mode 100644 index 0000000..9210941 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_address_validation.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_bridge_completion_validation.1.json b/contracts/teachlink/test_snapshots/test_bridge_completion_validation.1.json new file mode 100644 index 0000000..d3978c7 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_bridge_completion_validation.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 4, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_bridge_validation_edge_cases.1.json b/contracts/teachlink/test_snapshots/test_bridge_validation_edge_cases.1.json new file mode 100644 index 0000000..7e7ed26 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_bridge_validation_edge_cases.1.json @@ -0,0 +1,86 @@ +{ + "generators": { + "address": 3, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_cross_chain_validation.1.json b/contracts/teachlink/test_snapshots/test_cross_chain_validation.1.json new file mode 100644 index 0000000..12a5ba1 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_cross_chain_validation.1.json @@ -0,0 +1,111 @@ +{ + "generators": { + "address": 4, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_escrow_dispute_refund.1.json b/contracts/teachlink/test_snapshots/test_escrow_dispute_refund.1.json index a8781f2..330a5d9 100644 --- a/contracts/teachlink/test_snapshots/test_escrow_dispute_refund.1.json +++ b/contracts/teachlink/test_snapshots/test_escrow_dispute_refund.1.json @@ -21,7 +21,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" }, { - "i128": "800" + "i128": "1000" } ] } @@ -30,6 +30,7 @@ } ] ], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", @@ -92,7 +93,36 @@ "val": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 1 + } + } + ] } ] } @@ -225,6 +255,55 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "esc_an" + }, + "val": { + "map": [ + { + "key": { + "symbol": "average_resolution_time" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_disputes" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_escrows" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_resolved" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_volume" + }, + "val": { + "i128": "600" + } + } + ] + } + }, { "key": { "symbol": "esc_ct" @@ -328,7 +407,36 @@ "val": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 1 + } + } + ] } ] } @@ -366,6 +474,55 @@ } ] } + }, + { + "key": { + "symbol": "ins_pool" + }, + "val": { + "map": [ + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "max_payout_percentage" + }, + "val": { + "u32": 8000 + } + }, + { + "key": { + "symbol": "premium_rate" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "total_claims_paid" + }, + "val": { + "i128": "0" + } + } + ] + } } ] } @@ -418,7 +575,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" }, "val": { - "i128": "800" + "i128": "1000" } } ] diff --git a/contracts/teachlink/test_snapshots/test_escrow_release_flow.1.json b/contracts/teachlink/test_snapshots/test_escrow_release_flow.1.json index 71daf99..905f857 100644 --- a/contracts/teachlink/test_snapshots/test_escrow_release_flow.1.json +++ b/contracts/teachlink/test_snapshots/test_escrow_release_flow.1.json @@ -21,7 +21,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" }, { - "i128": "1000" + "i128": "2000" } ] } @@ -30,6 +30,7 @@ } ] ], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", @@ -92,10 +93,68 @@ "val": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 10 + } + } + ] }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Secondary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 5 + } + } + ] } ] } @@ -105,7 +164,7 @@ "symbol": "threshold" }, "val": { - "u32": 2 + "u32": 15 } }, { @@ -122,6 +181,26 @@ } }, "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "i128": "5" + } + ] + } + }, + "sub_invocations": [] + }, { "function": { "contract_fn": { @@ -216,6 +295,7 @@ ], [], [], + [], [] ], "ledger": { @@ -317,6 +397,55 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "symbol": "esc_an" + }, + "val": { + "map": [ + { + "key": { + "symbol": "average_resolution_time" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_disputes" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_escrows" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_resolved" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_volume" + }, + "val": { + "i128": "500" + } + } + ] + } + }, { "key": { "symbol": "esc_ct" @@ -350,7 +479,7 @@ "symbol": "approval_count" }, "val": { - "u32": 2 + "u32": 15 } }, { @@ -418,10 +547,68 @@ "val": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 10 + } + } + ] }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Secondary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 5 + } + } + ] } ] } @@ -443,7 +630,7 @@ "symbol": "threshold" }, "val": { - "u32": 2 + "u32": 15 } }, { @@ -459,6 +646,55 @@ } ] } + }, + { + "key": { + "symbol": "ins_pool" + }, + "val": { + "map": [ + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "5" + } + }, + { + "key": { + "symbol": "max_payout_percentage" + }, + "val": { + "u32": 8000 + } + }, + { + "key": { + "symbol": "premium_rate" + }, + "val": { + "u32": 100 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "total_claims_paid" + }, + "val": { + "i128": "0" + } + } + ] + } } ] } @@ -503,7 +739,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" }, "val": { - "i128": "0" + "i128": "5" } }, { @@ -511,7 +747,7 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" }, "val": { - "i128": "500" + "i128": "1495" } }, { diff --git a/contracts/teachlink/test_snapshots/test_escrow_validation_edge_cases.1.json b/contracts/teachlink/test_snapshots/test_escrow_validation_edge_cases.1.json new file mode 100644 index 0000000..58d31ac --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_escrow_validation_edge_cases.1.json @@ -0,0 +1,86 @@ +{ + "generators": { + "address": 9, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_professional_arbitration_picking.1.json b/contracts/teachlink/test_snapshots/test_professional_arbitration_picking.1.json new file mode 100644 index 0000000..c793325 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_professional_arbitration_picking.1.json @@ -0,0 +1,810 @@ +{ + "generators": { + "address": 7, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "register_arbitrator", + "args": [ + { + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "dispute_types_handled" + }, + "val": { + "vec": [] + } + }, + { + "key": { + "symbol": "is_active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "Expert Judge" + } + }, + { + "key": { + "symbol": "reputation_score" + }, + "val": { + "u32": 500 + } + }, + { + "key": { + "symbol": "specialization" + }, + "val": { + "vec": [] + } + }, + { + "key": { + "symbol": "total_resolved" + }, + "val": { + "u64": "0" + } + } + ] + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_escrow", + "args": [ + { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "100" + } + }, + { + "key": { + "symbol": "arbitrator" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "beneficiary" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + }, + { + "key": { + "symbol": "depositor" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "refund_time" + }, + "val": "void" + }, + { + "key": { + "symbol": "release_time" + }, + "val": "void" + }, + { + "key": { + "symbol": "signers" + }, + "val": { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 1 + } + } + ] + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + ] + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "i128": "100" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "dispute_escrow", + "args": [ + { + "u64": "1" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "bytes": "68656c70" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "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": { + "symbol": "arbs" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + "val": { + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "dispute_types_handled" + }, + "val": { + "vec": [] + } + }, + { + "key": { + "symbol": "is_active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "Expert Judge" + } + }, + { + "key": { + "symbol": "reputation_score" + }, + "val": { + "u32": 500 + } + }, + { + "key": { + "symbol": "specialization" + }, + "val": { + "vec": [] + } + }, + { + "key": { + "symbol": "total_resolved" + }, + "val": { + "u64": "0" + } + } + ] + } + } + ] + } + }, + { + "key": { + "symbol": "esc_an" + }, + "val": { + "map": [ + { + "key": { + "symbol": "average_resolution_time" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_disputes" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_escrows" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "total_resolved" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "total_volume" + }, + "val": { + "i128": "100" + } + } + ] + } + }, + { + "key": { + "symbol": "esc_ct" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "escrows" + }, + "val": { + "map": [ + { + "key": { + "u64": "1" + }, + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "100" + } + }, + { + "key": { + "symbol": "approval_count" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "arbitrator" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "beneficiary" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "depositor" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "dispute_reason" + }, + "val": { + "bytes": "68656c70" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u64": "1" + } + }, + { + "key": { + "symbol": "refund_time" + }, + "val": "void" + }, + { + "key": { + "symbol": "release_time" + }, + "val": "void" + }, + { + "key": { + "symbol": "signers" + }, + "val": { + "vec": [ + { + "map": [ + { + "key": { + "symbol": "address" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + } + }, + { + "key": { + "symbol": "role" + }, + "val": { + "vec": [ + { + "symbol": "Primary" + } + ] + } + }, + { + "key": { + "symbol": "weight" + }, + "val": { + "u32": 1 + } + } + ] + } + ] + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Disputed" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + ] + } + } + ] + } + }, + { + "key": { + "symbol": "ins_pool" + }, + "val": { + "map": [ + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "max_payout_percentage" + }, + "val": { + "u32": 8000 + } + }, + { + "key": { + "symbol": "premium_rate" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "token" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "symbol": "total_claims_paid" + }, + "val": { + "i128": "0" + } + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "symbol": "admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "balances" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + "val": { + "i128": "100" + } + }, + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + "val": { + "i128": "900" + } + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/teachlink/test_snapshots/test_rewards_validation_edge_cases.1.json b/contracts/teachlink/test_snapshots/test_rewards_validation_edge_cases.1.json new file mode 100644 index 0000000..076d568 --- /dev/null +++ b/contracts/teachlink/test_snapshots/test_rewards_validation_edge_cases.1.json @@ -0,0 +1,86 @@ +{ + "generators": { + "address": 4, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "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": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file From 5b2a52d01fc1854ea06a2ddb02fefb88db365d78 Mon Sep 17 00:00:00 2001 From: OthmanImam Date: Sun, 22 Feb 2026 18:51:59 +0100 Subject: [PATCH 4/5] updated --- contracts/credential_registry/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/credential_registry/src/lib.rs b/contracts/credential_registry/src/lib.rs index 21a1fd9..455d506 100644 --- a/contracts/credential_registry/src/lib.rs +++ b/contracts/credential_registry/src/lib.rs @@ -1,6 +1,8 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, contractevent, symbol_short, Address, Bytes, BytesN, Env}; +use soroban_sdk::{ + contract, contractevent, contractimpl, symbol_short, Address, Bytes, BytesN, Env, +}; #[contractevent] #[derive(Clone, Debug, Eq, PartialEq)] @@ -62,7 +64,8 @@ impl CredentialRegistryContract { subject_did, metadata_ptr, expires_at, - }.publish(env); + } + .publish(env); } // Revoke a credential. Caller must be issuer (signed address) @@ -84,7 +87,8 @@ impl CredentialRegistryContract { credential_hash, issuer_did, subject_did, - }.publish(env); + } + .publish(env); } None => panic!("credential not found"), } From 47f7ca66596afe4b0c5a4192e320655eec99531a Mon Sep 17 00:00:00 2001 From: OthmanImam Date: Sun, 22 Feb 2026 21:24:58 +0100 Subject: [PATCH 5/5] Update lib.rs --- contracts/identity_registry/src/lib.rs | 91 +++++++++++++++++++++----- 1 file changed, 76 insertions(+), 15 deletions(-) diff --git a/contracts/identity_registry/src/lib.rs b/contracts/identity_registry/src/lib.rs index 9fd5934..2a1b687 100644 --- a/contracts/identity_registry/src/lib.rs +++ b/contracts/identity_registry/src/lib.rs @@ -1,7 +1,51 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Bytes, BytesN, Env}; +use soroban_sdk::{ + contract, contractevent, contractimpl, symbol_short, Address, Bytes, BytesN, Env, +}; +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Didcrt { + pub identity_id: BytesN<32>, + pub controller: Address, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Didchg { + pub identity_id: BytesN<32>, + pub new_controller: Address, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Authset { + pub identity_id: BytesN<32>, + pub method_id: Bytes, + pub public_key: Bytes, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Authrem { + pub identity_id: BytesN<32>, + pub method_id: Bytes, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RecoverySet { + pub identity_id: BytesN<32>, + pub recovery: Address, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Didrec { + pub identity_id: BytesN<32>, + pub new_controller: Address, +} #[contract] pub struct IdentityRegistryContract; @@ -13,8 +57,11 @@ impl IdentityRegistryContract { let key = (symbol_short!("didctl"), identity_id.clone()); assert!(!env.storage().persistent().has(&key), "DID already exists"); env.storage().persistent().set(&key, &controller); - env.events() - .publish((symbol_short!("didcrt"),), (identity_id, controller)); + Didcrt { + identity_id, + controller, + } + .publish(env); } // Get controller for a DID @@ -40,8 +87,11 @@ impl IdentityRegistryContract { "only controller can change controller" ); env.storage().persistent().set(&key, &new_controller); - env.events() - .publish((symbol_short!("didchg"),), (identity_id, new_controller)); + Didchg { + identity_id, + new_controller, + } + .publish(env); } None => panic!("DID not found"), } @@ -69,10 +119,12 @@ impl IdentityRegistryContract { method_id.clone(), ); env.storage().persistent().set(&key, &public_key); - env.events().publish( - (symbol_short!("authset"),), - (identity_id, method_id, public_key), - ); + Authset { + identity_id, + method_id, + public_key, + } + .publish(env); } // Remove an auth method @@ -96,8 +148,11 @@ impl IdentityRegistryContract { method_id.clone(), ); env.storage().persistent().remove(&key); - env.events() - .publish((symbol_short!("authrem"),), (identity_id, method_id)); + Authrem { + identity_id, + method_id, + } + .publish(env); } // Set a recovery address that may be used to recover control of the DID @@ -117,8 +172,11 @@ impl IdentityRegistryContract { ); let key = (symbol_short!("recovery"), identity_id.clone()); env.storage().persistent().set(&key, &recovery); - env.events() - .publish((symbol_short!("recovery"),), (identity_id, recovery)); + RecoverySet { + identity_id, + recovery, + } + .publish(env); } // Recover controller using the configured recovery address @@ -134,8 +192,11 @@ impl IdentityRegistryContract { ); let ctrl_key = (symbol_short!("did_ctrl"), identity_id.clone()); env.storage().persistent().set(&ctrl_key, &new_controller); - env.events() - .publish((symbol_short!("didrec"),), (identity_id, new_controller)); + Didrec { + identity_id, + new_controller, + } + .publish(env); } None => panic!("no recovery configured for DID"), }