diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock
index 3e99add1..efe9de41 100644
--- a/contracts/Cargo.lock
+++ b/contracts/Cargo.lock
@@ -556,6 +556,20 @@ dependencies = [
"soroban-sdk",
]
+[[package]]
+name = "escrow-multisig"
+version = "0.1.0"
+dependencies = [
+ "soroban-sdk",
+]
+
+[[package]]
+name = "escrow-partial"
+version = "0.1.0"
+dependencies = [
+ "soroban-sdk",
+]
+
[[package]]
name = "ethnum"
version = "1.5.2"
@@ -994,6 +1008,13 @@ dependencies = [
"soroban-sdk",
]
+[[package]]
+name = "reputation-batch"
+version = "0.1.0"
+dependencies = [
+ "soroban-sdk",
+]
+
[[package]]
name = "rfc6979"
version = "0.4.0"
@@ -1164,6 +1185,13 @@ dependencies = [
"soroban-sdk",
]
+[[package]]
+name = "shipment-milestones"
+version = "0.1.0"
+dependencies = [
+ "soroban-sdk",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml
index dae5ad25..d1bc7d78 100644
--- a/contracts/Cargo.toml
+++ b/contracts/Cargo.toml
@@ -6,6 +6,10 @@ members = [
"escrow",
"document",
"reputation",
+ "package/escrow-multisig",
+ "package/escrow-partial",
+ "package/shipment-milestones",
+ "package/reputation-batch",
"package/upgradeable",
]
diff --git a/contracts/package/escrow-multisig/Cargo.toml b/contracts/package/escrow-multisig/Cargo.toml
new file mode 100644
index 00000000..df39a8ea
--- /dev/null
+++ b/contracts/package/escrow-multisig/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "escrow-multisig"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+crate-type = ["cdylib"]
+
+[features]
+testutils = ["soroban-sdk/testutils"]
+
+[dependencies]
+soroban-sdk = { version = "22.0.0", features = ["alloc"] }
+
+[dev-dependencies]
+soroban-sdk = { version = "22.0.0", features = ["testutils", "alloc"] }
+
+[profile.release]
+opt-level = "z"
+overflow-checks = true
+debug = 0
+strip = "symbols"
+debug-assertions = false
+panic = "abort"
+codegen-units = 1
+lto = true
diff --git a/contracts/package/escrow-multisig/src/lib.rs b/contracts/package/escrow-multisig/src/lib.rs
new file mode 100644
index 00000000..50276d09
--- /dev/null
+++ b/contracts/package/escrow-multisig/src/lib.rs
@@ -0,0 +1,473 @@
+#![no_std]
+
+use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env, Vec};
+
+// ── Errors ────────────────────────────────────────────────────────────────────
+
+#[contracterror]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(u32)]
+pub enum MultisigEscrowError {
+ NotInitialized = 1,
+ AlreadyInitialized = 2,
+ NotFound = 3,
+ InvalidThreshold = 4,
+ NotApprover = 5,
+ AlreadyReleased = 6,
+ AlreadyRefunded = 7,
+ Unauthorized = 8,
+}
+
+// ── Types ─────────────────────────────────────────────────────────────────────
+
+#[contracttype]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum EscrowMsStatus {
+ Active,
+ Released,
+ Refunded,
+}
+
+#[contracttype]
+#[derive(Clone, Debug)]
+pub struct MultisigEscrow {
+ pub escrow_id: u64,
+ pub shipper: Address,
+ pub carrier: Address,
+ pub amount: i128,
+ pub approvers: Vec
,
+ pub threshold: u32,
+ pub release_approvals: u32,
+ pub refund_approvals: u32,
+ pub status: EscrowMsStatus,
+}
+
+#[contracttype]
+pub enum DataKey {
+ Admin,
+ Counter,
+ Escrow(u64),
+ /// Bitmap of release approvals: escrow_id -> Vec
+ ReleaseMap(u64),
+ /// Bitmap of refund approvals: escrow_id -> Vec
+ RefundMap(u64),
+}
+
+const TTL_LEDGERS: u32 = 6_307_200;
+
+// ── Contract ──────────────────────────────────────────────────────────────────
+
+#[contract]
+pub struct MultisigEscrowContract;
+
+#[contractimpl]
+impl MultisigEscrowContract {
+ /// One-time initialization.
+ pub fn initialize(env: Env, admin: Address) -> Result<(), MultisigEscrowError> {
+ if env.storage().instance().has(&DataKey::Admin) {
+ return Err(MultisigEscrowError::AlreadyInitialized);
+ }
+ env.storage().instance().set(&DataKey::Admin, &admin);
+ env.storage().persistent().set(&DataKey::Counter, &0u64);
+ Ok(())
+ }
+
+ /// Create a new multi-sig escrow.
+ /// `approvers` is the list of addresses allowed to approve.
+ /// `threshold` is the number of approvals required (N-of-M).
+ pub fn create_escrow(
+ env: Env,
+ shipper: Address,
+ carrier: Address,
+ amount: i128,
+ approvers: Vec,
+ threshold: u32,
+ ) -> Result {
+ shipper.require_auth();
+
+ let m = approvers.len();
+ if threshold == 0 || threshold > m || m == 0 {
+ return Err(MultisigEscrowError::InvalidThreshold);
+ }
+
+ let escrow_id = Self::next_id(&env);
+
+ let escrow = MultisigEscrow {
+ escrow_id,
+ shipper,
+ carrier,
+ amount,
+ approvers: approvers.clone(),
+ threshold,
+ release_approvals: 0,
+ refund_approvals: 0,
+ status: EscrowMsStatus::Active,
+ };
+
+ // Initialize approval bitmaps as Vec of length M (all false)
+ let mut release_map = Vec::new(&env);
+ let mut refund_map = Vec::new(&env);
+ for _ in 0..m {
+ release_map.push_back(false);
+ refund_map.push_back(false);
+ }
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &escrow);
+ env.storage()
+ .persistent()
+ .set(&DataKey::ReleaseMap(escrow_id), &release_map);
+ env.storage()
+ .persistent()
+ .set(&DataKey::RefundMap(escrow_id), &refund_map);
+
+ Self::extend_ttl(&env, escrow_id);
+
+ Ok(escrow_id)
+ }
+
+ /// Approve fund release. Callable by any registered approver.
+ /// Duplicate approval from the same address is a no-op (idempotent).
+ /// Funds are released automatically when threshold is met.
+ pub fn approve_release(env: Env, approver: Address, escrow_id: u64) -> Result<(), MultisigEscrowError> {
+ approver.require_auth();
+
+ let mut escrow: MultisigEscrow = Self::load(&env, escrow_id)?;
+
+ if escrow.status == EscrowMsStatus::Released {
+ return Err(MultisigEscrowError::AlreadyReleased);
+ }
+ if escrow.status == EscrowMsStatus::Refunded {
+ return Err(MultisigEscrowError::AlreadyRefunded);
+ }
+
+ let index = Self::find_approver_index(&escrow.approvers, &approver)?;
+
+ let mut release_map: Vec = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ReleaseMap(escrow_id))
+ .ok_or(MultisigEscrowError::NotFound)?;
+
+ // Idempotent: if already approved, do nothing
+ if release_map.get(index).unwrap_or(false) {
+ return Ok(());
+ }
+
+ release_map.set(index, true);
+ escrow.release_approvals += 1;
+
+ // Check if threshold is met
+ if escrow.release_approvals >= escrow.threshold {
+ escrow.status = EscrowMsStatus::Released;
+ }
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &escrow);
+ env.storage()
+ .persistent()
+ .set(&DataKey::ReleaseMap(escrow_id), &release_map);
+ Self::extend_ttl(&env, escrow_id);
+
+ Ok(())
+ }
+
+ /// Approve refund. Requires threshold approvals OR admin override.
+ /// Duplicate approval from the same address is a no-op (idempotent).
+ pub fn approve_refund(env: Env, approver: Address, escrow_id: u64) -> Result<(), MultisigEscrowError> {
+ approver.require_auth();
+
+ let mut escrow: MultisigEscrow = Self::load(&env, escrow_id)?;
+
+ if escrow.status == EscrowMsStatus::Released {
+ return Err(MultisigEscrowError::AlreadyReleased);
+ }
+ if escrow.status == EscrowMsStatus::Refunded {
+ return Err(MultisigEscrowError::AlreadyRefunded);
+ }
+
+ let index = Self::find_approver_index(&escrow.approvers, &approver)?;
+
+ let mut refund_map: Vec = env
+ .storage()
+ .persistent()
+ .get(&DataKey::RefundMap(escrow_id))
+ .ok_or(MultisigEscrowError::NotFound)?;
+
+ // Idempotent
+ if refund_map.get(index).unwrap_or(false) {
+ return Ok(());
+ }
+
+ refund_map.set(index, true);
+ escrow.refund_approvals += 1;
+
+ if escrow.refund_approvals >= escrow.threshold {
+ escrow.status = EscrowMsStatus::Refunded;
+ }
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &escrow);
+ env.storage()
+ .persistent()
+ .set(&DataKey::RefundMap(escrow_id), &refund_map);
+ Self::extend_ttl(&env, escrow_id);
+
+ Ok(())
+ }
+
+ /// Admin override: force refund regardless of approvals.
+ pub fn admin_refund(env: Env, escrow_id: u64) -> Result<(), MultisigEscrowError> {
+ let admin: Address = env
+ .storage()
+ .instance()
+ .get(&DataKey::Admin)
+ .ok_or(MultisigEscrowError::NotInitialized)?;
+ admin.require_auth();
+
+ let mut escrow: MultisigEscrow = Self::load(&env, escrow_id)?;
+
+ if escrow.status == EscrowMsStatus::Released {
+ return Err(MultisigEscrowError::AlreadyReleased);
+ }
+ if escrow.status == EscrowMsStatus::Refunded {
+ return Err(MultisigEscrowError::AlreadyRefunded);
+ }
+
+ escrow.status = EscrowMsStatus::Refunded;
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &escrow);
+ Self::extend_ttl(&env, escrow_id);
+
+ Ok(())
+ }
+
+ // ── Queries ───────────────────────────────────────────────────────────
+
+ pub fn get_escrow(env: Env, escrow_id: u64) -> Result {
+ Self::load(&env, escrow_id)
+ }
+
+ pub fn get_release_approvals(env: Env, escrow_id: u64) -> Result {
+ let escrow: MultisigEscrow = Self::load(&env, escrow_id)?;
+ Ok(escrow.release_approvals)
+ }
+
+ pub fn get_refund_approvals(env: Env, escrow_id: u64) -> Result {
+ let escrow: MultisigEscrow = Self::load(&env, escrow_id)?;
+ Ok(escrow.refund_approvals)
+ }
+
+ // ── Helpers ───────────────────────────────────────────────────────────
+
+ fn load(env: &Env, escrow_id: u64) -> Result {
+ env.storage()
+ .persistent()
+ .get(&DataKey::Escrow(escrow_id))
+ .ok_or(MultisigEscrowError::NotFound)
+ }
+
+ fn find_approver_index(approvers: &Vec, approver: &Address) -> Result {
+ for i in 0..approvers.len() {
+ if approvers.get(i).unwrap() == *approver {
+ return Ok(i);
+ }
+ }
+ Err(MultisigEscrowError::NotApprover)
+ }
+
+ fn next_id(env: &Env) -> u64 {
+ let current: u64 = env
+ .storage()
+ .persistent()
+ .get(&DataKey::Counter)
+ .unwrap_or(0);
+ let next = current + 1;
+ env.storage().persistent().set(&DataKey::Counter, &next);
+ next
+ }
+
+ fn extend_ttl(env: &Env, escrow_id: u64) {
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::Escrow(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::ReleaseMap(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::RefundMap(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+ }
+}
+
+// ── Tests ─────────────────────────────────────────────────────────────────────
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use soroban_sdk::{testutils::Address as _, Env};
+
+ fn setup() -> (Env, Address, MultisigEscrowContractClient<'static>) {
+ let env = Env::default();
+ env.mock_all_auths();
+ let admin = Address::generate(&env);
+ let contract_id = env.register(MultisigEscrowContract {}, ());
+ let client = MultisigEscrowContractClient::new(&env, &contract_id);
+ client.initialize(&admin);
+ (env, admin, client)
+ }
+
+ #[test]
+ fn test_threshold_met_releases_funds() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+ let approver2 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+ approvers.push_back(approver2.clone());
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &2u32);
+
+ // First approval — not released yet
+ client.approve_release(&approver1, &id);
+ let escrow = client.get_escrow(&id);
+ assert_eq!(escrow.status, EscrowMsStatus::Active);
+ assert_eq!(escrow.release_approvals, 1);
+
+ // Second approval — threshold met, released
+ client.approve_release(&approver2, &id);
+ let escrow = client.get_escrow(&id);
+ assert_eq!(escrow.status, EscrowMsStatus::Released);
+ assert_eq!(escrow.release_approvals, 2);
+ }
+
+ #[test]
+ fn test_threshold_not_met_funds_held() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+ let approver2 = Address::generate(&env);
+ let approver3 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+ approvers.push_back(approver2.clone());
+ approvers.push_back(approver3.clone());
+
+ // threshold = 3 of 3
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &3u32);
+
+ client.approve_release(&approver1, &id);
+ client.approve_release(&approver2, &id);
+
+ // Only 2 of 3 — still Active
+ let escrow = client.get_escrow(&id);
+ assert_eq!(escrow.status, EscrowMsStatus::Active);
+ assert_eq!(escrow.release_approvals, 2);
+ }
+
+ #[test]
+ fn test_duplicate_approval_idempotent() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+ let approver2 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+ approvers.push_back(approver2.clone());
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &2u32);
+
+ // Approve once
+ client.approve_release(&approver1, &id);
+ // Approve again — idempotent, no panic
+ client.approve_release(&approver1, &id);
+
+ let escrow = client.get_escrow(&id);
+ assert_eq!(escrow.release_approvals, 1); // still 1
+ assert_eq!(escrow.status, EscrowMsStatus::Active);
+ }
+
+ #[test]
+ fn test_refund_threshold() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+ let approver2 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+ approvers.push_back(approver2.clone());
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &2u32);
+
+ client.approve_refund(&approver1, &id);
+ assert_eq!(client.get_escrow(&id).status, EscrowMsStatus::Active);
+
+ client.approve_refund(&approver2, &id);
+ assert_eq!(client.get_escrow(&id).status, EscrowMsStatus::Refunded);
+ }
+
+ #[test]
+ fn test_admin_override_refund() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &1u32);
+
+ client.admin_refund(&id);
+ assert_eq!(client.get_escrow(&id).status, EscrowMsStatus::Refunded);
+ }
+
+ #[test]
+ fn test_non_approver_rejected() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+ let stranger = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128, &approvers, &1u32);
+
+ let result = client.try_approve_release(&stranger, &id);
+ assert_eq!(result, Err(Ok(MultisigEscrowError::NotApprover)));
+ }
+
+ #[test]
+ fn test_invalid_threshold_rejected() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+ let approver1 = Address::generate(&env);
+
+ let mut approvers = Vec::new(&env);
+ approvers.push_back(approver1.clone());
+
+ // threshold > number of approvers
+ let result = client.try_create_escrow(&shipper, &carrier, &1000i128, &approvers, &5u32);
+ assert_eq!(result, Err(Ok(MultisigEscrowError::InvalidThreshold)));
+
+ // threshold = 0
+ let result = client.try_create_escrow(&shipper, &carrier, &1000i128, &approvers, &0u32);
+ assert_eq!(result, Err(Ok(MultisigEscrowError::InvalidThreshold)));
+ }
+}
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_admin_override_refund.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_admin_override_refund.1.json
new file mode 100644
index 00000000..ef265766
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_admin_override_refund.1.json
@@ -0,0 +1,479 @@
+{
+ "generators": {
+ "address": 5,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ },
+ {
+ "u32": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "admin_refund",
+ "args": [
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Refunded"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_duplicate_approval_idempotent.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_duplicate_approval_idempotent.1.json
new file mode 100644
index 00000000..1134a9ca
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_duplicate_approval_idempotent.1.json
@@ -0,0 +1,549 @@
+{
+ "generators": {
+ "address": 6,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ },
+ {
+ "u32": 2
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 2
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": true
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_invalid_threshold_rejected.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_invalid_threshold_rejected.1.json
new file mode 100644
index 00000000..966094a8
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_invalid_threshold_rejected.1.json
@@ -0,0 +1,130 @@
+{
+ "generators": {
+ "address": 5,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 0
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_non_approver_rejected.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_non_approver_rejected.1.json
new file mode 100644
index 00000000..127004a2
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_non_approver_rejected.1.json
@@ -0,0 +1,427 @@
+{
+ "generators": {
+ "address": 6,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ },
+ {
+ "u32": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 1
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_refund_threshold.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_refund_threshold.1.json
new file mode 100644
index 00000000..d40b913e
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_refund_threshold.1.json
@@ -0,0 +1,550 @@
+{
+ "generators": {
+ "address": 6,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ },
+ {
+ "u32": 2
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_refund",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_refund",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Refunded"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 2
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": true
+ },
+ {
+ "bool": true
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_met_releases_funds.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_met_releases_funds.1.json
new file mode 100644
index 00000000..73bb2b67
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_met_releases_funds.1.json
@@ -0,0 +1,550 @@
+{
+ "generators": {
+ "address": 6,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ },
+ {
+ "u32": 2
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Released"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 2
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": true
+ },
+ {
+ "bool": true
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_not_met_funds_held.1.json b/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_not_met_funds_held.1.json
new file mode 100644
index 00000000..ceb5f61b
--- /dev/null
+++ b/contracts/package/escrow-multisig/test_snapshots/tests/test_threshold_not_met_funds_held.1.json
@@ -0,0 +1,561 @@
+{
+ "generators": {
+ "address": 7,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ },
+ {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM"
+ }
+ ]
+ },
+ {
+ "u32": 3
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "approve_release",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "amount"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "approvers"
+ },
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "refund_approvals"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "release_approvals"
+ },
+ "val": {
+ "u32": 2
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "threshold"
+ },
+ "val": {
+ "u32": 3
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "RefundMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": false
+ },
+ {
+ "bool": false
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ReleaseMap"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "bool": true
+ },
+ {
+ "bool": true
+ },
+ {
+ "bool": false
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/Cargo.toml b/contracts/package/escrow-partial/Cargo.toml
new file mode 100644
index 00000000..e3d9a272
--- /dev/null
+++ b/contracts/package/escrow-partial/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "escrow-partial"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+crate-type = ["cdylib"]
+
+[features]
+testutils = ["soroban-sdk/testutils"]
+
+[dependencies]
+soroban-sdk = { version = "22.0.0", features = ["alloc"] }
+
+[dev-dependencies]
+soroban-sdk = { version = "22.0.0", features = ["testutils", "alloc"] }
+
+[profile.release]
+opt-level = "z"
+overflow-checks = true
+debug = 0
+strip = "symbols"
+debug-assertions = false
+panic = "abort"
+codegen-units = 1
+lto = true
diff --git a/contracts/package/escrow-partial/src/lib.rs b/contracts/package/escrow-partial/src/lib.rs
new file mode 100644
index 00000000..f0349eca
--- /dev/null
+++ b/contracts/package/escrow-partial/src/lib.rs
@@ -0,0 +1,325 @@
+#![no_std]
+
+use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env, Symbol};
+
+// ── Errors ────────────────────────────────────────────────────────────────────
+
+#[contracterror]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(u32)]
+pub enum PartialEscrowError {
+ NotInitialized = 1,
+ AlreadyInitialized = 2,
+ NotFound = 3,
+ Unauthorized = 4,
+ InsufficientFunds = 5,
+ InvalidAmount = 6,
+ AlreadyRefunded = 7,
+}
+
+// ── Types ─────────────────────────────────────────────────────────────────────
+
+#[contracttype]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum PartialEscrowStatus {
+ Active,
+ FullyReleased,
+ Refunded,
+}
+
+#[contracttype]
+#[derive(Clone, Debug)]
+pub struct PartialEscrowRecord {
+ pub escrow_id: u64,
+ pub shipper: Address,
+ pub carrier: Address,
+ pub total_funded: i128,
+ pub total_released: i128,
+ pub remaining: i128,
+ pub status: PartialEscrowStatus,
+}
+
+#[contracttype]
+pub enum DataKey {
+ Admin,
+ Counter,
+ Escrow(u64),
+}
+
+const TTL_LEDGERS: u32 = 6_307_200;
+
+// ── Contract ──────────────────────────────────────────────────────────────────
+
+#[contract]
+pub struct PartialEscrowContract;
+
+#[contractimpl]
+impl PartialEscrowContract {
+ /// One-time initialization.
+ pub fn initialize(env: Env, admin: Address) -> Result<(), PartialEscrowError> {
+ if env.storage().instance().has(&DataKey::Admin) {
+ return Err(PartialEscrowError::AlreadyInitialized);
+ }
+ env.storage().instance().set(&DataKey::Admin, &admin);
+ env.storage().persistent().set(&DataKey::Counter, &0u64);
+ Ok(())
+ }
+
+ /// Create a new partial-release escrow.
+ pub fn create_escrow(
+ env: Env,
+ shipper: Address,
+ carrier: Address,
+ amount: i128,
+ ) -> Result {
+ shipper.require_auth();
+
+ if amount <= 0 {
+ return Err(PartialEscrowError::InvalidAmount);
+ }
+
+ let escrow_id = Self::next_id(&env);
+
+ let record = PartialEscrowRecord {
+ escrow_id,
+ shipper,
+ carrier,
+ total_funded: amount,
+ total_released: 0,
+ remaining: amount,
+ status: PartialEscrowStatus::Active,
+ };
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &record);
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::Escrow(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+
+ Ok(escrow_id)
+ }
+
+ /// Release a partial amount of held funds to the carrier.
+ /// Emits a PartialRelease event with { amount, remaining_balance }.
+ pub fn release_partial(
+ env: Env,
+ escrow_id: u64,
+ amount: i128,
+ ) -> Result<(), PartialEscrowError> {
+ let admin: Address = env
+ .storage()
+ .instance()
+ .get(&DataKey::Admin)
+ .ok_or(PartialEscrowError::NotInitialized)?;
+ admin.require_auth();
+
+ if amount <= 0 {
+ return Err(PartialEscrowError::InvalidAmount);
+ }
+
+ let mut record: PartialEscrowRecord = Self::load(&env, escrow_id)?;
+
+ if record.status == PartialEscrowStatus::Refunded {
+ return Err(PartialEscrowError::AlreadyRefunded);
+ }
+
+ if amount > record.remaining {
+ return Err(PartialEscrowError::InsufficientFunds);
+ }
+
+ record.total_released += amount;
+ record.remaining -= amount;
+
+ if record.remaining == 0 {
+ record.status = PartialEscrowStatus::FullyReleased;
+ }
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &record);
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::Escrow(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+
+ // Emit PartialRelease event
+ env.events().publish(
+ (Symbol::new(&env, "PartialRelease"), escrow_id),
+ (amount, record.remaining),
+ );
+
+ Ok(())
+ }
+
+ /// Refund only the remaining (unreleased) amount to the shipper.
+ pub fn refund(env: Env, escrow_id: u64) -> Result {
+ let admin: Address = env
+ .storage()
+ .instance()
+ .get(&DataKey::Admin)
+ .ok_or(PartialEscrowError::NotInitialized)?;
+ admin.require_auth();
+
+ let mut record: PartialEscrowRecord = Self::load(&env, escrow_id)?;
+
+ if record.status == PartialEscrowStatus::Refunded {
+ return Err(PartialEscrowError::AlreadyRefunded);
+ }
+
+ let refund_amount = record.remaining;
+ record.remaining = 0;
+ record.status = PartialEscrowStatus::Refunded;
+
+ env.storage()
+ .persistent()
+ .set(&DataKey::Escrow(escrow_id), &record);
+ env.storage()
+ .persistent()
+ .extend_ttl(&DataKey::Escrow(escrow_id), TTL_LEDGERS, TTL_LEDGERS);
+
+ Ok(refund_amount)
+ }
+
+ // ── Queries ───────────────────────────────────────────────────────────
+
+ pub fn get_escrow(env: Env, escrow_id: u64) -> Result {
+ Self::load(&env, escrow_id)
+ }
+
+ // ── Helpers ───────────────────────────────────────────────────────────
+
+ fn load(env: &Env, escrow_id: u64) -> Result {
+ env.storage()
+ .persistent()
+ .get(&DataKey::Escrow(escrow_id))
+ .ok_or(PartialEscrowError::NotFound)
+ }
+
+ fn next_id(env: &Env) -> u64 {
+ let current: u64 = env
+ .storage()
+ .persistent()
+ .get(&DataKey::Counter)
+ .unwrap_or(0);
+ let next = current + 1;
+ env.storage().persistent().set(&DataKey::Counter, &next);
+ next
+ }
+}
+
+// ── Tests ─────────────────────────────────────────────────────────────────────
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use soroban_sdk::{testutils::{Address as _, Events}, Env};
+
+ fn setup() -> (Env, Address, PartialEscrowContractClient<'static>) {
+ let env = Env::default();
+ env.mock_all_auths();
+ let admin = Address::generate(&env);
+ let contract_id = env.register(PartialEscrowContract {}, ());
+ let client = PartialEscrowContractClient::new(&env, &contract_id);
+ client.initialize(&admin);
+ (env, admin, client)
+ }
+
+ #[test]
+ fn test_single_partial_release() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+
+ client.release_partial(&id, &300i128);
+
+ let record = client.get_escrow(&id);
+ assert_eq!(record.total_funded, 1000);
+ assert_eq!(record.total_released, 300);
+ assert_eq!(record.remaining, 700);
+ assert_eq!(record.status, PartialEscrowStatus::Active);
+ }
+
+ #[test]
+ fn test_multiple_partial_releases_sum_to_total() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+
+ client.release_partial(&id, &200i128);
+ client.release_partial(&id, &300i128);
+ client.release_partial(&id, &500i128);
+
+ let record = client.get_escrow(&id);
+ assert_eq!(record.total_funded, 1000);
+ assert_eq!(record.total_released, 1000);
+ assert_eq!(record.remaining, 0);
+ assert_eq!(record.status, PartialEscrowStatus::FullyReleased);
+ }
+
+ #[test]
+ fn test_over_release_rejected() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+
+ client.release_partial(&id, &800i128);
+
+ // Trying to release more than remaining
+ let result = client.try_release_partial(&id, &300i128);
+ assert_eq!(result, Err(Ok(PartialEscrowError::InsufficientFunds)));
+ }
+
+ #[test]
+ fn test_refund_returns_remaining_only() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+
+ // Release some first
+ client.release_partial(&id, &400i128);
+
+ // Refund should return only remaining
+ let refund_amount = client.refund(&id);
+ assert_eq!(refund_amount, 600);
+
+ let record = client.get_escrow(&id);
+ assert_eq!(record.remaining, 0);
+ assert_eq!(record.total_released, 400);
+ assert_eq!(record.status, PartialEscrowStatus::Refunded);
+ }
+
+ #[test]
+ fn test_release_after_refund_fails() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+ client.refund(&id);
+
+ let result = client.try_release_partial(&id, &100i128);
+ assert_eq!(result, Err(Ok(PartialEscrowError::AlreadyRefunded)));
+ }
+
+ #[test]
+ fn test_partial_release_emits_event() {
+ let (env, _, client) = setup();
+ let shipper = Address::generate(&env);
+ let carrier = Address::generate(&env);
+
+ let id = client.create_escrow(&shipper, &carrier, &1000i128);
+ client.release_partial(&id, &250i128);
+
+ // Verify event was emitted (events are captured in test env)
+ let events = env.events().all();
+ assert!(events.len() > 0);
+ }
+}
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_multiple_partial_releases_sum_to_total.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_multiple_partial_releases_sum_to_total.1.json
new file mode 100644
index 00000000..0f7e55e0
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_multiple_partial_releases_sum_to_total.1.json
@@ -0,0 +1,479 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 200
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 300
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 500
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 0
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "FullyReleased"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_over_release_rejected.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_over_release_rejected.1.json
new file mode 100644
index 00000000..1e8a46bd
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_over_release_rejected.1.json
@@ -0,0 +1,363 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 800
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 200
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 800
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_partial_release_emits_event.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_partial_release_emits_event.1.json
new file mode 100644
index 00000000..55f68adf
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_partial_release_emits_event.1.json
@@ -0,0 +1,399 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 250
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ]
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 750
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 250
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": [
+ {
+ "event": {
+ "ext": "v0",
+ "contract_id": "0000000000000000000000000000000000000000000000000000000000000002",
+ "type_": "contract",
+ "body": {
+ "v0": {
+ "topics": [
+ {
+ "symbol": "PartialRelease"
+ },
+ {
+ "u64": 1
+ }
+ ],
+ "data": {
+ "vec": [
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 250
+ }
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 750
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "failed_call": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_refund_returns_remaining_only.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_refund_returns_remaining_only.1.json
new file mode 100644
index 00000000..25cc4b22
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_refund_returns_remaining_only.1.json
@@ -0,0 +1,415 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 400
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "refund",
+ "args": [
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 0
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Refunded"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 400
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_release_after_refund_fails.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_release_after_refund_fails.1.json
new file mode 100644
index 00000000..e3a09ee9
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_release_after_refund_fails.1.json
@@ -0,0 +1,357 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "refund",
+ "args": [
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 0
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Refunded"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 0
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/escrow-partial/test_snapshots/tests/test_single_partial_release.1.json b/contracts/package/escrow-partial/test_snapshots/tests/test_single_partial_release.1.json
new file mode 100644
index 00000000..3c8dea31
--- /dev/null
+++ b/contracts/package/escrow-partial/test_snapshots/tests/test_single_partial_release.1.json
@@ -0,0 +1,363 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "create_escrow",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "release_partial",
+ "args": [
+ {
+ "u64": 1
+ },
+ {
+ "i128": {
+ "hi": 0,
+ "lo": 300
+ }
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Counter"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "u64": 1
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Escrow"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "carrier"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "escrow_id"
+ },
+ "val": {
+ "u64": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "remaining"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 700
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipper"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ },
+ {
+ "key": {
+ "symbol": "status"
+ },
+ "val": {
+ "vec": [
+ {
+ "symbol": "Active"
+ }
+ ]
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_funded"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 1000
+ }
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_released"
+ },
+ "val": {
+ "i128": {
+ "hi": 0,
+ "lo": 300
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/Cargo.toml b/contracts/package/reputation-batch/Cargo.toml
new file mode 100644
index 00000000..ff151d5e
--- /dev/null
+++ b/contracts/package/reputation-batch/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "reputation-batch"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+crate-type = ["cdylib"]
+
+[features]
+testutils = ["soroban-sdk/testutils"]
+
+[dependencies]
+soroban-sdk = { version = "22.0.0", features = ["alloc"] }
+
+[dev-dependencies]
+soroban-sdk = { version = "22.0.0", features = ["testutils", "alloc"] }
+
+[profile.release]
+opt-level = "z"
+overflow-checks = true
+debug = 0
+strip = "symbols"
+debug-assertions = false
+panic = "abort"
+codegen-units = 1
+lto = true
diff --git a/contracts/package/reputation-batch/src/lib.rs b/contracts/package/reputation-batch/src/lib.rs
new file mode 100644
index 00000000..d09d663c
--- /dev/null
+++ b/contracts/package/reputation-batch/src/lib.rs
@@ -0,0 +1,413 @@
+#![no_std]
+
+use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, BytesN, Env, Vec};
+
+// ── Errors ────────────────────────────────────────────────────────────────────
+
+#[contracterror]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(u32)]
+pub enum BatchRatingError {
+ NotInitialized = 1,
+ AlreadyInitialized = 2,
+ BatchLimitExceeded = 3,
+ InvalidScore = 4,
+ AlreadyRatedShipment = 5,
+ UserNotFound = 6,
+ EmptyBatch = 7,
+}
+
+// ── Types ─────────────────────────────────────────────────────────────────────
+
+const MAX_BATCH_SIZE: u32 = 10;
+
+#[contracttype]
+#[derive(Clone, Debug)]
+pub struct RatingEntry {
+ pub shipment_id: BytesN<32>,
+ pub ratee: Address,
+ pub score: u32,
+ pub timestamp: u64,
+}
+
+/// Reputation profile for a ratee.
+#[contracttype]
+#[derive(Clone, Debug)]
+pub struct ReputationProfile {
+ pub total_rating_points: u32,
+ pub rating_count: u32,
+ /// average_rating = total_rating_points / rating_count (score * 100 fixed-point)
+ pub average_rating: u32,
+}
+
+#[contracttype]
+pub enum DataKey {
+ Admin,
+ /// Reputation profile per ratee address.
+ Profile(Address),
+ /// Track who has rated a specific shipment: (shipment_id) -> Vec
+ ShipmentRaters(BytesN<32>),
+}
+
+const TTL_LEDGERS: u32 = 6_307_200;
+
+// ── Contract ──────────────────────────────────────────────────────────────────
+
+#[contract]
+pub struct ReputationBatchContract;
+
+#[contractimpl]
+impl ReputationBatchContract {
+ /// One-time initialization.
+ pub fn initialize(env: Env, admin: Address) -> Result<(), BatchRatingError> {
+ if env.storage().instance().has(&DataKey::Admin) {
+ return Err(BatchRatingError::AlreadyInitialized);
+ }
+ env.storage().instance().set(&DataKey::Admin, &admin);
+ Ok(())
+ }
+
+ /// Register a ratee so they can receive ratings.
+ pub fn register_ratee(env: Env, ratee: Address) -> Result<(), BatchRatingError> {
+ ratee.require_auth();
+
+ let key = DataKey::Profile(ratee);
+ if env.storage().persistent().has(&key) {
+ return Ok(()); // idempotent
+ }
+
+ let profile = ReputationProfile {
+ total_rating_points: 0,
+ rating_count: 0,
+ average_rating: 0,
+ };
+ env.storage().persistent().set(&key, &profile);
+ env.storage()
+ .persistent()
+ .extend_ttl(&key, TTL_LEDGERS, TTL_LEDGERS);
+ Ok(())
+ }
+
+ /// Submit a batch of ratings. All-or-nothing: if any entry fails validation,
+ /// the entire transaction is rolled back (panic via Soroban semantics).
+ ///
+ /// Validation per entry:
+ /// - score must be 1-5
+ /// - shipment must not already have a rating from this caller
+ /// - ratee must be a registered user
+ ///
+ /// Max 10 entries per batch.
+ pub fn add_ratings_batch(
+ env: Env,
+ rater: Address,
+ ratings: Vec,
+ ) -> Result<(), BatchRatingError> {
+ rater.require_auth();
+
+ let batch_size = ratings.len();
+ if batch_size == 0 {
+ return Err(BatchRatingError::EmptyBatch);
+ }
+ if batch_size > MAX_BATCH_SIZE {
+ return Err(BatchRatingError::BatchLimitExceeded);
+ }
+
+ // Validate ALL entries first (all-or-nothing)
+ for i in 0..batch_size {
+ let entry = ratings.get(i).unwrap();
+
+ if entry.score < 1 || entry.score > 5 {
+ return Err(BatchRatingError::InvalidScore);
+ }
+
+ // Check ratee is registered
+ if !env
+ .storage()
+ .persistent()
+ .has(&DataKey::Profile(entry.ratee.clone()))
+ {
+ return Err(BatchRatingError::UserNotFound);
+ }
+
+ // Check not already rated
+ let raters: Vec = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ShipmentRaters(entry.shipment_id.clone()))
+ .unwrap_or_else(|| Vec::new(&env));
+
+ if raters.contains(&rater) {
+ return Err(BatchRatingError::AlreadyRatedShipment);
+ }
+ }
+
+ // Apply all ratings
+ for i in 0..batch_size {
+ let entry = ratings.get(i).unwrap();
+
+ // Mark rater for this shipment
+ let ship_key = DataKey::ShipmentRaters(entry.shipment_id.clone());
+ let mut raters: Vec = env
+ .storage()
+ .persistent()
+ .get(&ship_key)
+ .unwrap_or_else(|| Vec::new(&env));
+ raters.push_back(rater.clone());
+ env.storage().persistent().set(&ship_key, &raters);
+ env.storage()
+ .persistent()
+ .extend_ttl(&ship_key, TTL_LEDGERS, TTL_LEDGERS);
+
+ // Update ratee's reputation profile
+ let profile_key = DataKey::Profile(entry.ratee.clone());
+ let mut profile: ReputationProfile = env
+ .storage()
+ .persistent()
+ .get(&profile_key)
+ .unwrap();
+
+ profile.total_rating_points += entry.score * 100;
+ profile.rating_count += 1;
+ profile.average_rating = profile.total_rating_points / profile.rating_count;
+
+ env.storage().persistent().set(&profile_key, &profile);
+ env.storage()
+ .persistent()
+ .extend_ttl(&profile_key, TTL_LEDGERS, TTL_LEDGERS);
+ }
+
+ Ok(())
+ }
+
+ // ── Queries ───────────────────────────────────────────────────────────
+
+ pub fn get_profile(env: Env, ratee: Address) -> Result {
+ env.storage()
+ .persistent()
+ .get(&DataKey::Profile(ratee))
+ .ok_or(BatchRatingError::UserNotFound)
+ }
+
+ pub fn has_rated_shipment(env: Env, shipment_id: BytesN<32>, rater: Address) -> bool {
+ let raters: Vec = env
+ .storage()
+ .persistent()
+ .get(&DataKey::ShipmentRaters(shipment_id))
+ .unwrap_or_else(|| Vec::new(&env));
+ raters.contains(&rater)
+ }
+}
+
+// ── Tests ─────────────────────────────────────────────────────────────────────
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use soroban_sdk::{
+ testutils::{Address as _, BytesN as _},
+ Env,
+ };
+
+ fn setup() -> (Env, Address, ReputationBatchContractClient<'static>) {
+ let env = Env::default();
+ env.mock_all_auths();
+ let admin = Address::generate(&env);
+ let contract_id = env.register(ReputationBatchContract {}, ());
+ let client = ReputationBatchContractClient::new(&env, &contract_id);
+ client.initialize(&admin);
+ (env, admin, client)
+ }
+
+ #[test]
+ fn test_all_valid_entries() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee = Address::generate(&env);
+
+ client.register_ratee(&ratee);
+
+ let ship1: BytesN<32> = BytesN::random(&env);
+ let ship2: BytesN<32> = BytesN::random(&env);
+ let ship3: BytesN<32> = BytesN::random(&env);
+
+ let mut ratings = Vec::new(&env);
+ ratings.push_back(RatingEntry {
+ shipment_id: ship1.clone(),
+ ratee: ratee.clone(),
+ score: 5,
+ timestamp: 1000,
+ });
+ ratings.push_back(RatingEntry {
+ shipment_id: ship2.clone(),
+ ratee: ratee.clone(),
+ score: 4,
+ timestamp: 2000,
+ });
+ ratings.push_back(RatingEntry {
+ shipment_id: ship3.clone(),
+ ratee: ratee.clone(),
+ score: 3,
+ timestamp: 3000,
+ });
+
+ client.add_ratings_batch(&rater, &ratings);
+
+ let profile = client.get_profile(&ratee);
+ assert_eq!(profile.rating_count, 3);
+ // (5+4+3)*100 / 3 = 400
+ assert_eq!(profile.average_rating, 400);
+
+ assert!(client.has_rated_shipment(&ship1, &rater));
+ assert!(client.has_rated_shipment(&ship2, &rater));
+ assert!(client.has_rated_shipment(&ship3, &rater));
+ }
+
+ #[test]
+ fn test_duplicate_entry_causes_full_rollback() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee = Address::generate(&env);
+
+ client.register_ratee(&ratee);
+
+ let ship1: BytesN<32> = BytesN::random(&env);
+
+ // First, submit a single rating for ship1
+ let mut first_batch = Vec::new(&env);
+ first_batch.push_back(RatingEntry {
+ shipment_id: ship1.clone(),
+ ratee: ratee.clone(),
+ score: 5,
+ timestamp: 1000,
+ });
+ client.add_ratings_batch(&rater, &first_batch);
+
+ // Now try a batch where ship1 is duplicated
+ let ship2: BytesN<32> = BytesN::random(&env);
+ let mut second_batch = Vec::new(&env);
+ second_batch.push_back(RatingEntry {
+ shipment_id: ship2.clone(),
+ ratee: ratee.clone(),
+ score: 4,
+ timestamp: 2000,
+ });
+ second_batch.push_back(RatingEntry {
+ shipment_id: ship1.clone(), // already rated!
+ ratee: ratee.clone(),
+ score: 3,
+ timestamp: 3000,
+ });
+
+ let result = client.try_add_ratings_batch(&rater, &second_batch);
+ assert_eq!(result, Err(Ok(BatchRatingError::AlreadyRatedShipment)));
+
+ // Profile should still show only the first rating (rollback)
+ let profile = client.get_profile(&ratee);
+ assert_eq!(profile.rating_count, 1);
+ assert_eq!(profile.average_rating, 500);
+ }
+
+ #[test]
+ fn test_batch_size_limit_exceeded() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee = Address::generate(&env);
+
+ client.register_ratee(&ratee);
+
+ // Create 11 entries (exceeds limit of 10)
+ let mut ratings = Vec::new(&env);
+ for _ in 0..11u32 {
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee.clone(),
+ score: 4,
+ timestamp: 1000,
+ });
+ }
+
+ let result = client.try_add_ratings_batch(&rater, &ratings);
+ assert_eq!(result, Err(Ok(BatchRatingError::BatchLimitExceeded)));
+ }
+
+ #[test]
+ fn test_invalid_score_causes_rollback() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee = Address::generate(&env);
+
+ client.register_ratee(&ratee);
+
+ let mut ratings = Vec::new(&env);
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee.clone(),
+ score: 5,
+ timestamp: 1000,
+ });
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee.clone(),
+ score: 6, // invalid!
+ timestamp: 2000,
+ });
+
+ let result = client.try_add_ratings_batch(&rater, &ratings);
+ assert_eq!(result, Err(Ok(BatchRatingError::InvalidScore)));
+
+ // No ratings should have been applied
+ let profile = client.get_profile(&ratee);
+ assert_eq!(profile.rating_count, 0);
+ }
+
+ #[test]
+ fn test_unregistered_ratee_causes_rollback() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee = Address::generate(&env); // NOT registered
+
+ let mut ratings = Vec::new(&env);
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee.clone(),
+ score: 4,
+ timestamp: 1000,
+ });
+
+ let result = client.try_add_ratings_batch(&rater, &ratings);
+ assert_eq!(result, Err(Ok(BatchRatingError::UserNotFound)));
+ }
+
+ #[test]
+ fn test_composite_score_recalculated_per_ratee() {
+ let (env, _, client) = setup();
+ let rater = Address::generate(&env);
+ let ratee1 = Address::generate(&env);
+ let ratee2 = Address::generate(&env);
+
+ client.register_ratee(&ratee1);
+ client.register_ratee(&ratee2);
+
+ let mut ratings = Vec::new(&env);
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee1.clone(),
+ score: 5,
+ timestamp: 1000,
+ });
+ ratings.push_back(RatingEntry {
+ shipment_id: BytesN::random(&env),
+ ratee: ratee2.clone(),
+ score: 3,
+ timestamp: 2000,
+ });
+
+ client.add_ratings_batch(&rater, &ratings);
+
+ let p1 = client.get_profile(&ratee1);
+ assert_eq!(p1.average_rating, 500); // 5 * 100
+
+ let p2 = client.get_profile(&ratee2);
+ assert_eq!(p2.average_rating, 300); // 3 * 100
+ }
+}
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_all_valid_entries.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_all_valid_entries.1.json
new file mode 100644
index 00000000..0bbe653e
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_all_valid_entries.1.json
@@ -0,0 +1,526 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_ratings_batch",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 5
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "924a3bc07186bd0e3be7f5c6b07c2e417f464e3644e272c544009228d2aa7d0f"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1000
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 4
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "94265d89bd46fea8f3e30c87419879bde7a3b764612bf8944bd53ba8b2cb8706"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 2000
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 3
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "d60dac07f80e276a70f6cdc9459d3250188a422d1c6dd407d2bc841c238ba7b1"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 3000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ [],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 400
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 3
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 1200
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "924a3bc07186bd0e3be7f5c6b07c2e417f464e3644e272c544009228d2aa7d0f"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "924a3bc07186bd0e3be7f5c6b07c2e417f464e3644e272c544009228d2aa7d0f"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "94265d89bd46fea8f3e30c87419879bde7a3b764612bf8944bd53ba8b2cb8706"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "94265d89bd46fea8f3e30c87419879bde7a3b764612bf8944bd53ba8b2cb8706"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "d60dac07f80e276a70f6cdc9459d3250188a422d1c6dd407d2bc841c238ba7b1"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "d60dac07f80e276a70f6cdc9459d3250188a422d1c6dd407d2bc841c238ba7b1"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_batch_size_limit_exceeded.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_batch_size_limit_exceeded.1.json
new file mode 100644
index 00000000..7a02a0d3
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_batch_size_limit_exceeded.1.json
@@ -0,0 +1,212 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_composite_score_recalculated_per_ratee.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_composite_score_recalculated_per_ratee.1.json
new file mode 100644
index 00000000..dc577ff3
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_composite_score_recalculated_per_ratee.1.json
@@ -0,0 +1,561 @@
+{
+ "generators": {
+ "address": 5,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_ratings_batch",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 5
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "65f5a6e6559be081f90f12672bbdfc35ff27805464aa2fc03456adb55a7b4429"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1000
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 3
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "1bae06f8e4f0c716d620bf42e69495ece3cc698bba27f169f56c6014443929e4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 2000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 500
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 500
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 300
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 300
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "1bae06f8e4f0c716d620bf42e69495ece3cc698bba27f169f56c6014443929e4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "1bae06f8e4f0c716d620bf42e69495ece3cc698bba27f169f56c6014443929e4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "65f5a6e6559be081f90f12672bbdfc35ff27805464aa2fc03456adb55a7b4429"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "65f5a6e6559be081f90f12672bbdfc35ff27805464aa2fc03456adb55a7b4429"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_duplicate_entry_causes_full_rollback.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_duplicate_entry_causes_full_rollback.1.json
new file mode 100644
index 00000000..799445fb
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_duplicate_entry_causes_full_rollback.1.json
@@ -0,0 +1,354 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_ratings_batch",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "ratee"
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ },
+ {
+ "key": {
+ "symbol": "score"
+ },
+ "val": {
+ "u32": 5
+ }
+ },
+ {
+ "key": {
+ "symbol": "shipment_id"
+ },
+ "val": {
+ "bytes": "ce9a295359b67943f49beffd104105d91dee4e353ca3da7aed5e5f1e9e5db4c3"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 500
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 1
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 500
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "ce9a295359b67943f49beffd104105d91dee4e353ca3da7aed5e5f1e9e5db4c3"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "ShipmentRaters"
+ },
+ {
+ "bytes": "ce9a295359b67943f49beffd104105d91dee4e353ca3da7aed5e5f1e9e5db4c3"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_invalid_score_causes_rollback.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_invalid_score_causes_rollback.1.json
new file mode 100644
index 00000000..f5438541
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_invalid_score_causes_rollback.1.json
@@ -0,0 +1,213 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "register_ratee",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Profile"
+ },
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "map": [
+ {
+ "key": {
+ "symbol": "average_rating"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "rating_count"
+ },
+ "val": {
+ "u32": 0
+ }
+ },
+ {
+ "key": {
+ "symbol": "total_rating_points"
+ },
+ "val": {
+ "u32": 0
+ }
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/reputation-batch/test_snapshots/tests/test_unregistered_ratee_causes_rollback.1.json b/contracts/package/reputation-batch/test_snapshots/tests/test_unregistered_ratee_causes_rollback.1.json
new file mode 100644
index 00000000..3a0477df
--- /dev/null
+++ b/contracts/package/reputation-batch/test_snapshots/tests/test_unregistered_ratee_causes_rollback.1.json
@@ -0,0 +1,90 @@
+{
+ "generators": {
+ "address": 4,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/Cargo.toml b/contracts/package/shipment-milestones/Cargo.toml
new file mode 100644
index 00000000..6612616d
--- /dev/null
+++ b/contracts/package/shipment-milestones/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "shipment-milestones"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+crate-type = ["cdylib"]
+
+[features]
+testutils = ["soroban-sdk/testutils"]
+
+[dependencies]
+soroban-sdk = { version = "22.0.0", features = ["alloc"] }
+
+[dev-dependencies]
+soroban-sdk = { version = "22.0.0", features = ["testutils", "alloc"] }
+
+[profile.release]
+opt-level = "z"
+overflow-checks = true
+debug = 0
+strip = "symbols"
+debug-assertions = false
+panic = "abort"
+codegen-units = 1
+lto = true
diff --git a/contracts/package/shipment-milestones/src/lib.rs b/contracts/package/shipment-milestones/src/lib.rs
new file mode 100644
index 00000000..9f9dd333
--- /dev/null
+++ b/contracts/package/shipment-milestones/src/lib.rs
@@ -0,0 +1,306 @@
+#![no_std]
+
+use soroban_sdk::{
+ contract, contracterror, contractimpl, contracttype, Address, BytesN, Env, String, Symbol, Vec,
+};
+
+// ── Errors ────────────────────────────────────────────────────────────────────
+
+#[contracterror]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(u32)]
+pub enum MilestoneError {
+ NotInitialized = 1,
+ AlreadyInitialized = 2,
+ Unauthorized = 3,
+ InvalidMilestoneType = 4,
+ MilestoneLimitReached = 5,
+}
+
+// ── Types ─────────────────────────────────────────────────────────────────────
+
+const MAX_MILESTONES: u32 = 20;
+
+#[contracttype]
+#[derive(Clone, Debug)]
+pub struct Milestone {
+ pub milestone_type: Symbol,
+ pub notes: String,
+ pub timestamp: u64,
+}
+
+#[contracttype]
+pub enum DataKey {
+ Admin,
+ /// Milestones for a shipment: shipment_id (BytesN<32>) -> Vec
+ Milestones(BytesN<32>),
+}
+
+const TTL_LEDGERS: u32 = 6_307_200;
+
+// ── Contract ──────────────────────────────────────────────────────────────────
+
+#[contract]
+pub struct ShipmentMilestonesContract;
+
+#[contractimpl]
+impl ShipmentMilestonesContract {
+ /// One-time initialization.
+ pub fn initialize(env: Env, admin: Address) -> Result<(), MilestoneError> {
+ if env.storage().instance().has(&DataKey::Admin) {
+ return Err(MilestoneError::AlreadyInitialized);
+ }
+ env.storage().instance().set(&DataKey::Admin, &admin);
+ Ok(())
+ }
+
+ /// Add a milestone to a shipment.
+ /// Supported milestone_type values: CUSTOMS_CLEARED, PORT_ARRIVAL,
+ /// OUT_FOR_DELIVERY, DELAY, EXCEPTION
+ pub fn add_milestone(
+ env: Env,
+ caller: Address,
+ shipment_id: BytesN<32>,
+ milestone_type: Symbol,
+ notes: String,
+ timestamp: u64,
+ ) -> Result<(), MilestoneError> {
+ caller.require_auth();
+
+ // Validate milestone type
+ if !Self::is_valid_milestone_type(&env, &milestone_type) {
+ return Err(MilestoneError::InvalidMilestoneType);
+ }
+
+ let key = DataKey::Milestones(shipment_id.clone());
+
+ let mut milestones: Vec = env
+ .storage()
+ .persistent()
+ .get(&key)
+ .unwrap_or_else(|| Vec::new(&env));
+
+ if milestones.len() >= MAX_MILESTONES {
+ return Err(MilestoneError::MilestoneLimitReached);
+ }
+
+ let milestone = Milestone {
+ milestone_type,
+ notes,
+ timestamp,
+ };
+
+ milestones.push_back(milestone);
+
+ // Sort by timestamp ascending (insertion sort — milestones are few)
+ let len = milestones.len();
+ for i in 1..len {
+ let mut j = i;
+ while j > 0 {
+ let prev = milestones.get(j - 1).unwrap();
+ let curr = milestones.get(j).unwrap();
+ if prev.timestamp > curr.timestamp {
+ milestones.set(j - 1, curr);
+ milestones.set(j, prev);
+ j -= 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ env.storage().persistent().set(&key, &milestones);
+ env.storage()
+ .persistent()
+ .extend_ttl(&key, TTL_LEDGERS, TTL_LEDGERS);
+
+ Ok(())
+ }
+
+ /// Get all milestones for a shipment, ordered by timestamp ascending.
+ pub fn get_milestones(env: Env, shipment_id: BytesN<32>) -> Vec {
+ let key = DataKey::Milestones(shipment_id);
+ env.storage()
+ .persistent()
+ .get(&key)
+ .unwrap_or_else(|| Vec::new(&env))
+ }
+
+ // ── Helpers ───────────────────────────────────────────────────────────
+
+ fn is_valid_milestone_type(env: &Env, milestone_type: &Symbol) -> bool {
+ let valid_types = [
+ Symbol::new(env, "CUSTOMS_CLEARED"),
+ Symbol::new(env, "PORT_ARRIVAL"),
+ Symbol::new(env, "OUT_FOR_DELIVERY"),
+ Symbol::new(env, "DELAY"),
+ Symbol::new(env, "EXCEPTION"),
+ ];
+ for vt in valid_types.iter() {
+ if milestone_type == vt {
+ return true;
+ }
+ }
+ false
+ }
+}
+
+// ── Tests ─────────────────────────────────────────────────────────────────────
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use soroban_sdk::{
+ testutils::{Address as _, BytesN as _},
+ Env,
+ };
+
+ fn setup() -> (Env, Address, ShipmentMilestonesContractClient<'static>) {
+ let env = Env::default();
+ env.mock_all_auths();
+ let admin = Address::generate(&env);
+ let contract_id = env.register(ShipmentMilestonesContract {}, ());
+ let client = ShipmentMilestonesContractClient::new(&env, &contract_id);
+ client.initialize(&admin);
+ (env, admin, client)
+ }
+
+ #[test]
+ fn test_add_valid_milestone() {
+ let (env, _, client) = setup();
+ let caller = Address::generate(&env);
+ let shipment_id = BytesN::random(&env);
+
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "CUSTOMS_CLEARED"),
+ &String::from_str(&env, "Cleared at Lagos port"),
+ &1000u64,
+ );
+
+ let milestones = client.get_milestones(&shipment_id);
+ assert_eq!(milestones.len(), 1);
+
+ let m = milestones.get(0).unwrap();
+ assert_eq!(m.milestone_type, Symbol::new(&env, "CUSTOMS_CLEARED"));
+ assert_eq!(m.timestamp, 1000);
+ }
+
+ #[test]
+ fn test_milestone_limit_reached() {
+ let (env, _, client) = setup();
+ let caller = Address::generate(&env);
+ let shipment_id = BytesN::random(&env);
+
+ // Add 20 milestones (the max)
+ for i in 0..20u64 {
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "DELAY"),
+ &String::from_str(&env, "delay note"),
+ &(i + 1),
+ );
+ }
+
+ // 21st should fail
+ let result = client.try_add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "DELAY"),
+ &String::from_str(&env, "one too many"),
+ &21u64,
+ );
+ assert_eq!(result, Err(Ok(MilestoneError::MilestoneLimitReached)));
+ }
+
+ #[test]
+ fn test_milestones_ordered_by_timestamp() {
+ let (env, _, client) = setup();
+ let caller = Address::generate(&env);
+ let shipment_id = BytesN::random(&env);
+
+ // Add out of order
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "PORT_ARRIVAL"),
+ &String::from_str(&env, "arrived at port"),
+ &3000u64,
+ );
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "CUSTOMS_CLEARED"),
+ &String::from_str(&env, "customs done"),
+ &1000u64,
+ );
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "OUT_FOR_DELIVERY"),
+ &String::from_str(&env, "on the way"),
+ &5000u64,
+ );
+
+ let milestones = client.get_milestones(&shipment_id);
+ assert_eq!(milestones.len(), 3);
+ assert_eq!(milestones.get(0).unwrap().timestamp, 1000);
+ assert_eq!(milestones.get(1).unwrap().timestamp, 3000);
+ assert_eq!(milestones.get(2).unwrap().timestamp, 5000);
+ }
+
+ #[test]
+ fn test_invalid_milestone_type_rejected() {
+ let (env, _, client) = setup();
+ let caller = Address::generate(&env);
+ let shipment_id = BytesN::random(&env);
+
+ let result = client.try_add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, "INVALID_TYPE"),
+ &String::from_str(&env, "bad type"),
+ &1000u64,
+ );
+ assert_eq!(result, Err(Ok(MilestoneError::InvalidMilestoneType)));
+ }
+
+ #[test]
+ fn test_all_valid_milestone_types() {
+ let (env, _, client) = setup();
+ let caller = Address::generate(&env);
+ let shipment_id = BytesN::random(&env);
+
+ let types = [
+ "CUSTOMS_CLEARED",
+ "PORT_ARRIVAL",
+ "OUT_FOR_DELIVERY",
+ "DELAY",
+ "EXCEPTION",
+ ];
+
+ for (i, t) in types.iter().enumerate() {
+ client.add_milestone(
+ &caller,
+ &shipment_id,
+ &Symbol::new(&env, t),
+ &String::from_str(&env, "note"),
+ &((i as u64) + 1),
+ );
+ }
+
+ let milestones = client.get_milestones(&shipment_id);
+ assert_eq!(milestones.len(), 5);
+ }
+
+ #[test]
+ fn test_empty_milestones_returns_empty_vec() {
+ let (env, _, client) = setup();
+ let shipment_id = BytesN::random(&env);
+
+ let milestones = client.get_milestones(&shipment_id);
+ assert_eq!(milestones.len(), 0);
+ }
+}
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_add_valid_milestone.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_add_valid_milestone.1.json
new file mode 100644
index 00000000..95bf7689
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_add_valid_milestone.1.json
@@ -0,0 +1,228 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "4c151ec4fceaf76e5a2713532c6ed7088be99cb8f68c49ad9ee964e87bd45c34"
+ },
+ {
+ "symbol": "CUSTOMS_CLEARED"
+ },
+ {
+ "string": "Cleared at Lagos port"
+ },
+ {
+ "u64": 1000
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "4c151ec4fceaf76e5a2713532c6ed7088be99cb8f68c49ad9ee964e87bd45c34"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "4c151ec4fceaf76e5a2713532c6ed7088be99cb8f68c49ad9ee964e87bd45c34"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "CUSTOMS_CLEARED"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "Cleared at Lagos port"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_all_valid_milestone_types.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_all_valid_milestone_types.1.json
new file mode 100644
index 00000000..c0f05bd9
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_all_valid_milestone_types.1.json
@@ -0,0 +1,596 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ },
+ {
+ "symbol": "CUSTOMS_CLEARED"
+ },
+ {
+ "string": "note"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ },
+ {
+ "symbol": "PORT_ARRIVAL"
+ },
+ {
+ "string": "note"
+ },
+ {
+ "u64": 2
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ },
+ {
+ "symbol": "OUT_FOR_DELIVERY"
+ },
+ {
+ "string": "note"
+ },
+ {
+ "u64": 3
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "note"
+ },
+ {
+ "u64": 4
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ },
+ {
+ "symbol": "EXCEPTION"
+ },
+ {
+ "string": "note"
+ },
+ {
+ "u64": 5
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "2d56469392dc138baf8822f0f1e10751c5549013a656a01fed76d04ddcbfac14"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "CUSTOMS_CLEARED"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "PORT_ARRIVAL"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 2
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "OUT_FOR_DELIVERY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 3
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 4
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "EXCEPTION"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 5
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2032731177588607455
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2032731177588607455
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_empty_milestones_returns_empty_vec.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_empty_milestones_returns_empty_vec.1.json
new file mode 100644
index 00000000..fa021d43
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_empty_milestones_returns_empty_vec.1.json
@@ -0,0 +1,90 @@
+{
+ "generators": {
+ "address": 2,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_invalid_milestone_type_rejected.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_invalid_milestone_type_rejected.1.json
new file mode 100644
index 00000000..c13d27d0
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_invalid_milestone_type_rejected.1.json
@@ -0,0 +1,90 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_milestone_limit_reached.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_milestone_limit_reached.1.json
new file mode 100644
index 00000000..1f615bfd
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_milestone_limit_reached.1.json
@@ -0,0 +1,1976 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 1
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 2
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 3
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 4
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 5
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 6
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 7
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 8
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 9
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 10
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 11
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 12
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 13
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 14
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 15
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 16
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 17
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 18
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 19
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ },
+ {
+ "symbol": "DELAY"
+ },
+ {
+ "string": "delay note"
+ },
+ {
+ "u64": 20
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "318adf6bb11ad736576b07fffbe6df24f6b999248161b114d7a0c6b748433c42"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 2
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 3
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 4
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 5
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 6
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 7
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 8
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 9
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 10
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 11
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 12
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 13
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 14
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 15
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 16
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 17
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 18
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 19
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "DELAY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "delay note"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 20
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 115220454072064130
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 115220454072064130
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1194852393571756375
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1194852393571756375
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1301173170172112462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1301173170172112462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2032731177588607455
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2032731177588607455
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2307661404550649928
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2307661404550649928
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2578412842719982537
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2578412842719982537
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2781962168096793370
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 2781962168096793370
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 3126073502131104533
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 3126073502131104533
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4270020994084947596
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4270020994084947596
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4571470874178140630
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4571470874178140630
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 4837995959683129791
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5806905060045992000
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5806905060045992000
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6277191135259896685
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6277191135259896685
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6391496069076573377
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6391496069076573377
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6517132746326325848
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 6517132746326325848
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 7270604957039011794
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 7270604957039011794
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 8370022561469687789
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 8370022561469687789
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file
diff --git a/contracts/package/shipment-milestones/test_snapshots/tests/test_milestones_ordered_by_timestamp.1.json b/contracts/package/shipment-milestones/test_snapshots/tests/test_milestones_ordered_by_timestamp.1.json
new file mode 100644
index 00000000..f308a458
--- /dev/null
+++ b/contracts/package/shipment-milestones/test_snapshots/tests/test_milestones_ordered_by_timestamp.1.json
@@ -0,0 +1,412 @@
+{
+ "generators": {
+ "address": 3,
+ "nonce": 0
+ },
+ "auth": [
+ [],
+ [],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "9cc49ced9260d3f6532843f82ae1b3194bed9139c1d797718b0fbe44aff19db2"
+ },
+ {
+ "symbol": "PORT_ARRIVAL"
+ },
+ {
+ "string": "arrived at port"
+ },
+ {
+ "u64": 3000
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "9cc49ced9260d3f6532843f82ae1b3194bed9139c1d797718b0fbe44aff19db2"
+ },
+ {
+ "symbol": "CUSTOMS_CLEARED"
+ },
+ {
+ "string": "customs done"
+ },
+ {
+ "u64": 1000
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ [
+ [
+ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ {
+ "function": {
+ "contract_fn": {
+ "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "function_name": "add_milestone",
+ "args": [
+ {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
+ },
+ {
+ "bytes": "9cc49ced9260d3f6532843f82ae1b3194bed9139c1d797718b0fbe44aff19db2"
+ },
+ {
+ "symbol": "OUT_FOR_DELIVERY"
+ },
+ {
+ "string": "on the way"
+ },
+ {
+ "u64": 5000
+ }
+ ]
+ }
+ },
+ "sub_invocations": []
+ }
+ ]
+ ],
+ []
+ ],
+ "ledger": {
+ "protocol_version": 22,
+ "sequence_number": 0,
+ "timestamp": 0,
+ "network_id": "0000000000000000000000000000000000000000000000000000000000000000",
+ "base_reserve": 0,
+ "min_persistent_entry_ttl": 4096,
+ "min_temp_entry_ttl": 16,
+ "max_entry_ttl": 6312000,
+ "ledger_entries": [
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "9cc49ced9260d3f6532843f82ae1b3194bed9139c1d797718b0fbe44aff19db2"
+ }
+ ]
+ },
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": {
+ "vec": [
+ {
+ "symbol": "Milestones"
+ },
+ {
+ "bytes": "9cc49ced9260d3f6532843f82ae1b3194bed9139c1d797718b0fbe44aff19db2"
+ }
+ ]
+ },
+ "durability": "persistent",
+ "val": {
+ "vec": [
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "CUSTOMS_CLEARED"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "customs done"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 1000
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "PORT_ARRIVAL"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "arrived at port"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 3000
+ }
+ }
+ ]
+ },
+ {
+ "map": [
+ {
+ "key": {
+ "symbol": "milestone_type"
+ },
+ "val": {
+ "symbol": "OUT_FOR_DELIVERY"
+ }
+ },
+ {
+ "key": {
+ "symbol": "notes"
+ },
+ "val": {
+ "string": "on the way"
+ }
+ },
+ {
+ "key": {
+ "symbol": "timestamp"
+ },
+ "val": {
+ "u64": 5000
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 6307200
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4",
+ "key": "ledger_key_contract_instance",
+ "durability": "persistent"
+ }
+ },
+ [
+ {
+ "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": [
+ {
+ "key": {
+ "vec": [
+ {
+ "symbol": "Admin"
+ }
+ ]
+ },
+ "val": {
+ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 801925984706572462
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 1033654523790656264
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_data": {
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_data": {
+ "ext": "v0",
+ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
+ "key": {
+ "ledger_key_nonce": {
+ "nonce": 5541220902715666415
+ }
+ },
+ "durability": "temporary",
+ "val": "void"
+ }
+ },
+ "ext": "v0"
+ },
+ 6311999
+ ]
+ ],
+ [
+ {
+ "contract_code": {
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }
+ },
+ [
+ {
+ "last_modified_ledger_seq": 0,
+ "data": {
+ "contract_code": {
+ "ext": "v0",
+ "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "code": ""
+ }
+ },
+ "ext": "v0"
+ },
+ 4095
+ ]
+ ]
+ ]
+ },
+ "events": []
+}
\ No newline at end of file