From c8605b52ccead89e8bf9e7329214b26fa50eed4e Mon Sep 17 00:00:00 2001 From: Victor Oladimeji Date: Wed, 29 Jul 2026 08:50:41 +0100 Subject: [PATCH] feat(auction): bump TTL on hot storage reads Add persistent-storage-backed auctions with create_auction/get_auction entrypoints. get_auction is the contract's hot read path, so every call extends the auction record's TTL back to a full lifetime once it drops below the refresh threshold, keeping frequently-read, rarely-written auctions clear of archival eviction. Closes #1115 --- contracts/auction/src/lib.rs | 125 +++++++- contracts/auction/src/test.rs | 153 +++++++++- ...tion_ids_increment_across_creations.1.json | 277 ++++++++++++++++++ .../test_capabilities_is_read_only.1.json | 62 ++++ .../test_capabilities_returns_bitmap.1.json | 61 ++++ ..._create_auction_rejects_id_overflow.1.json | 75 +++++ ..._rejects_non_positive_reserve_price.1.json | 62 ++++ ...create_auction_requires_seller_auth.1.json | 175 +++++++++++ ...tion_bumps_ttl_when_below_threshold.1.json | 178 +++++++++++ ...not_shrink_ttl_when_above_threshold.1.json | 177 +++++++++++ .../test/test_get_auction_not_found.1.json | 61 ++++ ...est_get_auction_returns_stored_data.1.json | 176 +++++++++++ 12 files changed, 1578 insertions(+), 4 deletions(-) create mode 100644 contracts/auction/test_snapshots/test/test_auction_ids_increment_across_creations.1.json create mode 100644 contracts/auction/test_snapshots/test/test_capabilities_is_read_only.1.json create mode 100644 contracts/auction/test_snapshots/test/test_capabilities_returns_bitmap.1.json create mode 100644 contracts/auction/test_snapshots/test/test_create_auction_rejects_id_overflow.1.json create mode 100644 contracts/auction/test_snapshots/test/test_create_auction_rejects_non_positive_reserve_price.1.json create mode 100644 contracts/auction/test_snapshots/test/test_create_auction_requires_seller_auth.1.json create mode 100644 contracts/auction/test_snapshots/test/test_get_auction_bumps_ttl_when_below_threshold.1.json create mode 100644 contracts/auction/test_snapshots/test/test_get_auction_does_not_shrink_ttl_when_above_threshold.1.json create mode 100644 contracts/auction/test_snapshots/test/test_get_auction_not_found.1.json create mode 100644 contracts/auction/test_snapshots/test/test_get_auction_returns_stored_data.1.json diff --git a/contracts/auction/src/lib.rs b/contracts/auction/src/lib.rs index bbde9cc8..bca53a9d 100644 --- a/contracts/auction/src/lib.rs +++ b/contracts/auction/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, Env}; +use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env}; /// Bitmap of supported auction capabilities. /// Clients can read this to detect feature deltas across deployments. @@ -11,6 +11,58 @@ use soroban_sdk::{contract, contractimpl, Env}; /// bit 3: cancellable auctions pub const CAPABILITIES: u64 = 0b1111; +/// Minimum remaining ledgers an auction record may have before it is +/// refreshed on a hot read. At ~5 s/ledger, 7 days ≈ 120_960 ledgers. +/// +/// Keeping this well above zero means a record is bumped on read long +/// before it is at risk of archival eviction, even if reads cluster right +/// before expiry. +pub const AUCTION_TTL_THRESHOLD: u32 = 17_280 * 7; + +/// Ledgers to extend an auction record's TTL to when it is bumped, either on +/// creation or on a hot read below [`AUCTION_TTL_THRESHOLD`]. At ~5 s/ledger, +/// 30 days ≈ 518_400 ledgers. +/// +/// Uses `extend_ttl()` semantics, which only ever extend a TTL forward, so +/// bumping is idempotent and safe to call unconditionally on every read. +pub const AUCTION_TTL_EXTEND_TO: u32 = 17_280 * 30; + +/// Persistent storage keys used by the Auction contract. +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum DataKey { + /// An individual auction record, keyed by auction id. + Auction(u64), + /// Counter used to allocate the next auction id. + NextAuctionId, +} + +/// Data describing a single auction. +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AuctionData { + /// The address that created the auction and receives sale proceeds. + pub seller: Address, + /// Minimum acceptable sale price. Must be strictly positive. + pub reserve_price: i128, + /// Ledger timestamp (seconds) at which the auction was created. + pub created_at: u64, + /// Whether the auction is still open. + pub active: bool, +} + +/// Errors returned by the Auction contract. +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Error { + /// No auction exists for the given id. + AuctionNotFound = 1, + /// `reserve_price` was not strictly positive. + InvalidReservePrice = 2, + /// The auction id counter would overflow `u64`. + AuctionIdOverflow = 3, +} + #[contract] pub struct Auction; @@ -21,8 +73,77 @@ impl Auction { pub fn capabilities(_env: Env) -> u64 { CAPABILITIES } + + /// Creates a new auction owned by `seller` with the given `reserve_price`. + /// + /// The new record is written to persistent storage with its TTL set to + /// [`AUCTION_TTL_EXTEND_TO`] ledgers so it starts with a full lifetime. + /// + /// # Authorization + /// `seller` must authenticate via `require_auth()`. + /// + /// # Errors + /// - [`Error::InvalidReservePrice`] if `reserve_price` is not strictly positive. + /// - [`Error::AuctionIdOverflow`] if the auction id counter has been exhausted. + pub fn create_auction(env: Env, seller: Address, reserve_price: i128) -> Result { + seller.require_auth(); + + if reserve_price <= 0 { + return Err(Error::InvalidReservePrice); + } + + let next_id: u64 = env + .storage() + .instance() + .get(&DataKey::NextAuctionId) + .unwrap_or(0); + let following_id = next_id.checked_add(1).ok_or(Error::AuctionIdOverflow)?; + env.storage() + .instance() + .set(&DataKey::NextAuctionId, &following_id); + + let data = AuctionData { + seller, + reserve_price, + created_at: env.ledger().timestamp(), + active: true, + }; + + let key = DataKey::Auction(next_id); + env.storage().persistent().set(&key, &data); + env.storage() + .persistent() + .extend_ttl(&key, AUCTION_TTL_THRESHOLD, AUCTION_TTL_EXTEND_TO); + + Ok(next_id) + } + + /// Returns the data for the auction identified by `auction_id`. + /// + /// This is the contract's hot read path: bidders and off-chain indexers + /// are expected to call it far more often than auctions are created or + /// modified. Every call bumps the record's persistent TTL back up to + /// [`AUCTION_TTL_EXTEND_TO`] ledgers whenever it has dropped below + /// [`AUCTION_TTL_THRESHOLD`], so a frequently-read, rarely-written + /// auction never falls prey to archival eviction. + /// + /// # Errors + /// - [`Error::AuctionNotFound`] if no auction exists for `auction_id`. + pub fn get_auction(env: Env, auction_id: u64) -> Result { + let key = DataKey::Auction(auction_id); + let data: AuctionData = env + .storage() + .persistent() + .get(&key) + .ok_or(Error::AuctionNotFound)?; + + env.storage() + .persistent() + .extend_ttl(&key, AUCTION_TTL_THRESHOLD, AUCTION_TTL_EXTEND_TO); + + Ok(data) + } } #[cfg(test)] mod test; - diff --git a/contracts/auction/src/test.rs b/contracts/auction/src/test.rs index 745967dd..66ca2b6c 100644 --- a/contracts/auction/src/test.rs +++ b/contracts/auction/src/test.rs @@ -1,8 +1,12 @@ -#![cfg(test)] - use super::*; +use soroban_sdk::testutils::storage::Persistent as _; +use soroban_sdk::testutils::{Address as _, Ledger as _}; use soroban_sdk::Env; +fn setup(env: &Env) -> soroban_sdk::Address { + env.register(Auction, ()) +} + #[test] fn test_capabilities_returns_bitmap() { let env = Env::default(); @@ -26,3 +30,148 @@ fn test_capabilities_is_read_only() { assert_eq!(a, b, "capabilities must be idempotent"); } +#[test] +fn test_create_auction_requires_seller_auth() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let id = client.create_auction(&seller, &1_000); + assert_eq!(id, 0); + assert_eq!( + env.auths()[0].0, + seller, + "create_auction must require the seller's authorization" + ); +} + +#[test] +fn test_create_auction_rejects_non_positive_reserve_price() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let zero_result = client.try_create_auction(&seller, &0); + assert_eq!(zero_result, Err(Ok(Error::InvalidReservePrice))); + + let negative_result = client.try_create_auction(&seller, &-1); + assert_eq!(negative_result, Err(Ok(Error::InvalidReservePrice))); +} + +#[test] +fn test_auction_ids_increment_across_creations() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let first = client.create_auction(&seller, &500); + let second = client.create_auction(&seller, &750); + assert_eq!(first, 0); + assert_eq!(second, 1); +} + +#[test] +fn test_get_auction_returns_stored_data() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let id = client.create_auction(&seller, &1_234); + let data = client.get_auction(&id); + + assert_eq!(data.seller, seller); + assert_eq!(data.reserve_price, 1_234); + assert!(data.active); +} + +#[test] +fn test_get_auction_not_found() { + let env = Env::default(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + + let result = client.try_get_auction(&42); + assert_eq!(result, Err(Ok(Error::AuctionNotFound))); +} + +#[test] +fn test_create_auction_rejects_id_overflow() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + env.as_contract(&contract_id, || { + env.storage() + .instance() + .set(&DataKey::NextAuctionId, &u64::MAX); + }); + + let result = client.try_create_auction(&seller, &10); + assert_eq!(result, Err(Ok(Error::AuctionIdOverflow))); +} + +#[test] +fn test_get_auction_bumps_ttl_when_below_threshold() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let id = client.create_auction(&seller, &1_000); + + env.as_contract(&contract_id, || { + let key = DataKey::Auction(id); + assert_eq!( + env.storage().persistent().get_ttl(&key), + AUCTION_TTL_EXTEND_TO + ); + + env.ledger().with_mut(|li| { + li.sequence_number += AUCTION_TTL_EXTEND_TO - AUCTION_TTL_THRESHOLD + 1; + }); + assert!(env.storage().persistent().get_ttl(&key) < AUCTION_TTL_THRESHOLD); + }); + + client.get_auction(&id); + + env.as_contract(&contract_id, || { + let key = DataKey::Auction(id); + assert_eq!( + env.storage().persistent().get_ttl(&key), + AUCTION_TTL_EXTEND_TO, + "a hot read below the threshold must restore the full TTL" + ); + }); +} + +#[test] +fn test_get_auction_does_not_shrink_ttl_when_above_threshold() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = setup(&env); + let client = AuctionClient::new(&env, &contract_id); + let seller = soroban_sdk::Address::generate(&env); + + let id = client.create_auction(&seller, &1_000); + client.get_auction(&id); + + env.as_contract(&contract_id, || { + let key = DataKey::Auction(id); + assert_eq!( + env.storage().persistent().get_ttl(&key), + AUCTION_TTL_EXTEND_TO, + "extend_ttl only ever extends, never shortens" + ); + }); +} diff --git a/contracts/auction/test_snapshots/test/test_auction_ids_increment_across_creations.1.json b/contracts/auction/test_snapshots/test/test_auction_ids_increment_across_creations.1.json new file mode 100644 index 00000000..286e9a12 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_auction_ids_increment_across_creations.1.json @@ -0,0 +1,277 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "500" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "750" + } + ] + } + }, + "sub_invocations": [] + } + ] + ] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "500" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "750" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "2" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_capabilities_is_read_only.1.json b/contracts/auction/test_snapshots/test/test_capabilities_is_read_only.1.json new file mode 100644 index 00000000..0628e979 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_capabilities_is_read_only.1.json @@ -0,0 +1,62 @@ +{ + "generators": { + "address": 1, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_capabilities_returns_bitmap.1.json b/contracts/auction/test_snapshots/test/test_capabilities_returns_bitmap.1.json new file mode 100644 index 00000000..53df41d1 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_capabilities_returns_bitmap.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 1, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_create_auction_rejects_id_overflow.1.json b/contracts/auction/test_snapshots/test/test_create_auction_rejects_id_overflow.1.json new file mode 100644 index 00000000..d758cf4e --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_create_auction_rejects_id_overflow.1.json @@ -0,0 +1,75 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "18446744073709551615" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_create_auction_rejects_non_positive_reserve_price.1.json b/contracts/auction/test_snapshots/test/test_create_auction_rejects_non_positive_reserve_price.1.json new file mode 100644 index 00000000..4a5a349e --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_create_auction_rejects_non_positive_reserve_price.1.json @@ -0,0 +1,62 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_create_auction_requires_seller_auth.1.json b/contracts/auction/test_snapshots/test/test_create_auction_requires_seller_auth.1.json new file mode 100644 index 00000000..e0f86267 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_create_auction_requires_seller_auth.1.json @@ -0,0 +1,175 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "1000" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_get_auction_bumps_ttl_when_below_threshold.1.json b/contracts/auction/test_snapshots/test/test_get_auction_bumps_ttl_when_below_threshold.1.json new file mode 100644 index 00000000..186cd5d8 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_get_auction_bumps_ttl_when_below_threshold.1.json @@ -0,0 +1,178 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 397441, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "1000" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 915841 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 401536 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_get_auction_does_not_shrink_ttl_when_above_threshold.1.json b/contracts/auction/test_snapshots/test/test_get_auction_does_not_shrink_ttl_when_above_threshold.1.json new file mode 100644 index 00000000..a5d11e06 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_get_auction_does_not_shrink_ttl_when_above_threshold.1.json @@ -0,0 +1,177 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "1000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "1000" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_get_auction_not_found.1.json b/contracts/auction/test_snapshots/test/test_get_auction_not_found.1.json new file mode 100644 index 00000000..53df41d1 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_get_auction_not_found.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 1, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contracts/auction/test_snapshots/test/test_get_auction_returns_stored_data.1.json b/contracts/auction/test_snapshots/test/test_get_auction_returns_stored_data.1.json new file mode 100644 index 00000000..50a9cc35 --- /dev/null +++ b/contracts/auction/test_snapshots/test/test_get_auction_returns_stored_data.1.json @@ -0,0 +1,176 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "create_auction", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "1234" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "vec": [ + { + "symbol": "Auction" + }, + { + "u64": "0" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "active" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "created_at" + }, + "val": { + "u64": "0" + } + }, + { + "key": { + "symbol": "reserve_price" + }, + "val": { + "i128": "1234" + } + }, + { + "key": { + "symbol": "seller" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "NextAuctionId" + } + ] + }, + "val": { + "u64": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file