From 3e25275e0e92b3ace52ac3ec0cf7a2c37a392eb0 Mon Sep 17 00:00:00 2001 From: DeePrincipal-dev-lang Date: Thu, 28 May 2026 09:09:31 +0000 Subject: [PATCH] feat: add metadata field and accessor to commitment --- contracts/escrow/src/lib.rs | 12 +++++++++++- contracts/escrow/src/test.rs | 22 ++++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/contracts/escrow/src/lib.rs b/contracts/escrow/src/lib.rs index 677f1757..14abb7d9 100644 --- a/contracts/escrow/src/lib.rs +++ b/contracts/escrow/src/lib.rs @@ -15,7 +15,7 @@ //! `fund_escrow`, `release`, `refund`, and `dispute`. use soroban_sdk::{ - contract, contracterror, contractimpl, contracttype, Address, Env, String, Symbol, Vec, + contract, contracterror, contractimpl, contracttype, Address, Env, Map, String, Symbol, Vec, }; /// Storage keys for persistent contract state. @@ -79,6 +79,9 @@ pub struct Commitment { /// Compliance score 0..=100 recorded by the attestation engine. pub compliance_score: u32, pub created_at: u64, + /// Arbitrary key-value metadata supplied at creation time (e.g. risk notes, + /// off-chain context). Keys and values are both `String`. Empty by default. + pub metadata: Map, } /// Errors returned to the caller. Numeric codes are stable and surfaced by the @@ -140,6 +143,7 @@ impl EscrowContract { risk: RiskProfile, duration_days: u32, penalty_bps: u32, + metadata: Map, ) -> Result { Self::require_init(&env)?; owner.require_auth(); @@ -169,6 +173,7 @@ impl EscrowContract { penalty_bps, compliance_score: 100, created_at: now, + metadata, }; env.storage() @@ -366,6 +371,11 @@ impl EscrowContract { Self::load(&env, commitment_id) } + /// Return the metadata map stored on a commitment. + pub fn get_metadata(env: Env, commitment_id: u64) -> Result, Error> { + Ok(Self::load(&env, commitment_id)?.metadata) + } + /// Return the list of commitment ids owned by an address. pub fn get_owner_commitments(env: Env, owner: Address) -> Vec { env.storage() diff --git a/contracts/escrow/src/test.rs b/contracts/escrow/src/test.rs index 11d7b7f2..87e640fc 100644 --- a/contracts/escrow/src/test.rs +++ b/contracts/escrow/src/test.rs @@ -2,9 +2,10 @@ use super::*; use soroban_sdk::{ + map, testutils::{Address as _, Ledger as _}, token::{StellarAssetClient, TokenClient}, - Address, Env, String, + Address, Env, Map, String, }; /// Spins up a test environment with a Stellar Asset Contract token and a @@ -70,7 +71,7 @@ fn create_and_fund_locks_funds() { let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300, &Map::new(&f.env)); let c = f.client.get_commitment(&id); assert_eq!(c.status, EscrowStatus::Created); assert_eq!(c.amount, 1_000); @@ -87,7 +88,7 @@ fn release_after_maturity_returns_principal() { fund_owner(&f, &owner, 1_000); let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Safe, &10, &200); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Safe, &10, &200, &Map::new(&f.env)); f.client.fund_escrow(&id); // Advance ledger time past maturity. @@ -105,7 +106,7 @@ fn release_before_maturity_fails() { fund_owner(&f, &owner, 1_000); let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Safe, &10, &200); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Safe, &10, &200, &Map::new(&f.env)); f.client.fund_escrow(&id); let res = f.client.try_release(&id, &owner); @@ -120,7 +121,7 @@ fn refund_applies_penalty_to_fee_recipient() { // 5% penalty. let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Aggressive, &30, &500); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Aggressive, &30, &500, &Map::new(&f.env)); f.client.fund_escrow(&id); let refunded = f.client.refund(&id); @@ -137,7 +138,7 @@ fn dispute_freezes_then_admin_resolves() { fund_owner(&f, &owner, 1_000); let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300, &Map::new(&f.env)); f.client.fund_escrow(&id); f.client @@ -161,7 +162,7 @@ fn create_rejects_invalid_amount() { let owner = Address::generate(&f.env); let res = f.client - .try_create_commitment(&owner, &f.asset, &0, &RiskProfile::Safe, &30, &200); + .try_create_commitment(&owner, &f.asset, &0, &RiskProfile::Safe, &30, &200, &Map::new(&f.env)); assert_eq!(res, Err(Ok(Error::InvalidAmount))); } @@ -176,6 +177,7 @@ fn create_rejects_excessive_penalty() { &RiskProfile::Safe, &30, &20_000, + &Map::new(&f.env), ); assert_eq!(res, Err(Ok(Error::PenaltyTooHigh))); } @@ -187,7 +189,7 @@ fn record_attestation_clamps_score() { let attestor = Address::generate(&f.env); let id = f .client - .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300); + .create_commitment(&owner, &f.asset, &1_000, &RiskProfile::Balanced, &30, &300, &Map::new(&f.env)); f.client.record_attestation(&id, &attestor, &250); assert_eq!(f.client.get_commitment(&id).compliance_score, 100); } @@ -198,10 +200,10 @@ fn owner_index_tracks_commitments() { let owner = Address::generate(&f.env); let a = f .client - .create_commitment(&owner, &f.asset, &100, &RiskProfile::Safe, &30, &200); + .create_commitment(&owner, &f.asset, &100, &RiskProfile::Safe, &30, &200, &Map::new(&f.env)); let b = f .client - .create_commitment(&owner, &f.asset, &200, &RiskProfile::Balanced, &30, &300); + .create_commitment(&owner, &f.asset, &200, &RiskProfile::Balanced, &30, &300, &Map::new(&f.env)); let ids = f.client.get_owner_commitments(&owner); assert_eq!(ids.len(), 2); assert_eq!(ids.get(0).unwrap(), a);