diff --git a/Cargo.toml b/Cargo.toml index 8381944..cfa13fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ members = [ "contracts/governance", "contracts/insurance", "contracts/teachlink", - "contracts/documentation", + "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..455d506 --- /dev/null +++ b/contracts/credential_registry/src/lib.rs @@ -0,0 +1,123 @@ +#![no_std] + +use soroban_sdk::{ + contract, contractevent, contractimpl, 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; + +#[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); + Crediss { + credential_hash, + issuer_did, + subject_did, + metadata_ptr, + expires_at, + } + .publish(env); + } + + // 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); + Credrev { + credential_hash, + issuer_did, + subject_did, + } + .publish(env); + } + 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..2a1b687 --- /dev/null +++ b/contracts/identity_registry/src/lib.rs @@ -0,0 +1,206 @@ +#![no_std] + +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; + +#[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); + Didcrt { + identity_id, + controller, + } + .publish(env); + } + + // 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); + Didchg { + identity_id, + new_controller, + } + .publish(env); + } + 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); + Authset { + identity_id, + method_id, + public_key, + } + .publish(env); + } + + // 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); + Authrem { + identity_id, + method_id, + } + .publish(env); + } + + // 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); + RecoverySet { + identity_id, + recovery, + } + .publish(env); + } + + // 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); + Didrec { + identity_id, + new_controller, + } + .publish(env); + } + None => panic!("no recovery configured for DID"), + } + } +} + +fn main() {} 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