diff --git a/examples/contracts/oracle/Cargo.toml b/examples/contracts/oracle/Cargo.toml new file mode 100644 index 0000000..aca60f0 --- /dev/null +++ b/examples/contracts/oracle/Cargo.toml @@ -0,0 +1,31 @@ +[workspace] + +[package] +name = "soroban-oracle" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { version = "22.0.0" } + +[dev-dependencies] +soroban-sdk = { version = "22.0.0", features = ["testutils"] } + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true diff --git a/examples/contracts/oracle/README.md b/examples/contracts/oracle/README.md new file mode 100644 index 0000000..f4ad9a5 --- /dev/null +++ b/examples/contracts/oracle/README.md @@ -0,0 +1,217 @@ +# Oracle Price Feed Contract + +A Soroban smart-contract example that stores external asset prices on-chain +and demonstrates how to **debug stale or incorrect price data** with the +Soroban Debugger. + +--- + +## Overview + +| Function | Description | +|---|---| +| `initialize(admin, stale_ttl)` | Bootstrap the oracle – sets the admin address and the staleness TTL in seconds | +| `set_price(asset, price)` | Admin-only; writes a price (micro-units) and the current ledger timestamp | +| `get_price(asset)` | Returns the latest price in micro-units | +| `get_timestamp(asset)` | Returns the UNIX timestamp of the last price update | +| `is_stale(asset)` | Returns `true` when `now − last_timestamp > stale_ttl` | +| `get_stale_ttl()` | Returns the configured staleness window (seconds) | + +Prices are stored in **micro-units** so integer arithmetic avoids floating-point +issues. For example, a price of `$1.10` is stored as `1_100_000`. + +--- + +## Building + +```bash +# From the repo root +cd examples/contracts/oracle + +# Install the wasm32 target if not already present +rustup target add wasm32-unknown-unknown + +# Build a release WASM +cargo build --target wasm32-unknown-unknown --release + +# The compiled WASM lands here: +# target/wasm32-unknown-unknown/release/soroban_oracle.wasm +``` + +Run the unit tests (uses the Soroban test framework, no WASM target needed): + +```bash +cargo test +``` + +--- + +## Storage Layout + +The contract uses two storage tiers: + +| Storage tier | Key | Value | Notes | +|---|---|---|---| +| `instance` | `Admin` | `Address` | Set once at init | +| `instance` | `StaleTtl` | `u64` (seconds) | Set once at init | +| `persistent` | `Price(asset)` | `i128` (micro-units) | Updated on every `set_price` | +| `persistent` | `Timestamp(asset)` | `u64` (UNIX seconds) | Updated on every `set_price` | + +Using `persistent` storage for price/timestamp entries means each asset's data +survives ledger close independently and can be observed individually in a +storage diff. + +--- + +## Debugging Stale Price Scenarios + +### Scenario: Consumer contract rejects a stale price + +A downstream lending protocol calls `is_stale("XLM")` and receives `true`, +causing a transaction to fail. Use the debugger to trace exactly when the +price went stale. + +### Step 1 – Reproduce the failing invocation + +```bash +soroban-debugger invoke \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --id oracle_contract \ + --fn is_stale \ + --arg '"XLM"' \ + --snapshot examples/snapshot.json \ + --ledger-time 1_720_000_000 +``` + +Expected output (stale price): + +``` +Result: true +``` + +### Step 2 – Inspect stored timestamp + +```bash +soroban-debugger invoke \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --id oracle_contract \ + --fn get_timestamp \ + --arg '"XLM"' \ + --snapshot examples/snapshot.json +``` + +Sample output: + +``` +Result: 1719999000 +``` + +Calculate the age: + +``` +age = 1_720_000_000 − 1_719_999_000 = 1_000 seconds +stale_ttl = 300 seconds +→ price is stale (1000 > 300) +``` + +### Step 3 – View storage diff after a fresh price push + +Run `set_price` and capture the storage diff to confirm both `Price` and +`Timestamp` entries are updated atomically: + +```bash +soroban-debugger invoke \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --id oracle_contract \ + --fn set_price \ + --arg '"XLM"' --arg '1100000' \ + --snapshot examples/snapshot.json \ + --diff +``` + +Example storage diff output: + +``` +Storage diff for contract oracle_contract +───────────────────────────────────────── + MODIFIED persistent::Price("XLM") + before: 1_050_000 + after: 1_100_000 + + MODIFIED persistent::Timestamp("XLM") + before: 1_719_999_000 + after: 1_720_000_000 +───────────────────────────────────────── +``` + +The diff confirms that both the price and its timestamp moved forward in the +same invocation – no partial update is possible. + +### Step 4 – Confirm price is fresh + +```bash +soroban-debugger invoke \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --id oracle_contract \ + --fn is_stale \ + --arg '"XLM"' \ + --snapshot examples/snapshot.json \ + --ledger-time 1_720_000_000 +``` + +``` +Result: false +``` + +--- + +## Watch Mode – monitor staleness in real time + +Use the debugger's watch mode to alert you whenever an asset's price crosses +the staleness threshold during a batch replay: + +```bash +soroban-debugger watch \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --snapshot examples/snapshot.json \ + --watch 'persistent::Timestamp("XLM")' \ + --batch examples/batch_args.json +``` + +The debugger will emit a diff event each time the watched key changes. + +--- + +## Step-Through Debugging + +Open an interactive debug session to step through `is_stale` instruction by +instruction and inspect each storage read: + +```bash +soroban-debugger debug \ + --wasm target/wasm32-unknown-unknown/release/soroban_oracle.wasm \ + --fn is_stale \ + --arg '"ETH"' \ + --snapshot examples/snapshot.json +``` + +Useful debugger commands inside the session: + +| Command | Description | +|---|---| +| `n` / `next` | Advance one WASM instruction | +| `s storage` | Dump current contract storage | +| `w persistent::Timestamp("ETH")` | Watch a specific storage key | +| `b is_stale` | Set a breakpoint on function entry | +| `q` | Quit the session | + +--- + +## Common Root Causes for Stale Prices + +| Symptom | Likely Cause | Fix | +|---|---|---| +| `is_stale` always `true` | Relayer stopped submitting `set_price` | Restart or re-deploy the price-feed relayer | +| Timestamp frozen | `set_price` transactions failing auth | Verify admin key rotation | +| Price correct but timestamp old | Clock skew between relayer and ledger | Sync relayer to ledger timestamp source | +| Wrong asset symbol | Ticker case mismatch (`xlm` vs `XLM`) | Normalise to uppercase before calling | diff --git a/examples/contracts/oracle/src/lib.rs b/examples/contracts/oracle/src/lib.rs new file mode 100644 index 0000000..2c32a51 --- /dev/null +++ b/examples/contracts/oracle/src/lib.rs @@ -0,0 +1,364 @@ +#![no_std] + +use soroban_sdk::{ + contract, contracterror, contractimpl, contracttype, symbol_short, Address, Env, String, +}; + +// ------------------------------------------------------------------- +// Storage Keys +// ------------------------------------------------------------------- + +/// Each price entry is stored per asset symbol so a single oracle +/// contract can track many different price feeds simultaneously. +#[derive(Clone)] +#[contracttype] +pub enum DataKey { + /// Latest price (in micro-units, e.g. 1_000_000 = $1.00) for an asset. + Price(String), + /// UNIX timestamp (seconds) of the last price update for an asset. + Timestamp(String), + /// Maximum age (in seconds) before a price is considered stale. + StaleTtl, + /// Admin address – the only address allowed to push price updates. + Admin, +} + +// ------------------------------------------------------------------- +// Errors +// ------------------------------------------------------------------- + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum OracleError { + /// No price has been recorded for the requested asset yet. + AssetNotFound = 1, + /// The price value must be strictly greater than zero. + InvalidPrice = 2, + /// Only the admin may push price updates. + Unauthorized = 3, + /// The contract has already been initialized. + AlreadyInitialized = 4, + /// The staleness TTL must be greater than zero. + InvalidTtl = 5, +} + +// ------------------------------------------------------------------- +// Contract +// ------------------------------------------------------------------- + +#[contract] +pub struct OraclePriceFeed; + +#[contractimpl] +impl OraclePriceFeed { + + // --------------------------------------------------------------- + // Initialization + // --------------------------------------------------------------- + + /// Initialize the oracle with an admin address and a staleness TTL. + /// + /// * `admin` – Address that is authorised to call `set_price`. + /// * `stale_ttl` – Number of seconds after which a price is stale. + pub fn initialize( + env: Env, + admin: Address, + stale_ttl: u64, + ) -> Result<(), OracleError> { + if env.storage().instance().has(&DataKey::Admin) { + return Err(OracleError::AlreadyInitialized); + } + if stale_ttl == 0 { + return Err(OracleError::InvalidTtl); + } + + admin.require_auth(); + + env.storage().instance().set(&DataKey::Admin, &admin); + env.storage().instance().set(&DataKey::StaleTtl, &stale_ttl); + + env.events().publish( + (symbol_short!("init"),), + (admin.clone(), stale_ttl), + ); + + Ok(()) + } + + // --------------------------------------------------------------- + // Write – set_price + // --------------------------------------------------------------- + + /// Record a new price for `asset` at the current ledger timestamp. + /// + /// * `asset` – Uppercase ticker symbol, e.g. `"XLM"`, `"BTC"`. + /// * `price` – Price expressed in micro-units (1 USD = 1_000_000). + /// + /// Only the admin may call this function. + /// + /// **Storage diff produced (visible in the debugger):** + /// ``` + /// BEFORE Price("XLM") = Timestamp("XLM") = + /// AFTER Price("XLM") = Timestamp("XLM") = + /// ``` + pub fn set_price( + env: Env, + asset: String, + price: i128, + ) -> Result<(), OracleError> { + if price <= 0 { + return Err(OracleError::InvalidPrice); + } + + // Admin authorisation check. + let admin: Address = env + .storage() + .instance() + .get(&DataKey::Admin) + .unwrap(); + admin.require_auth(); + + // Current ledger time acts as the canonical timestamp. + let now: u64 = env.ledger().timestamp(); + + env.storage() + .persistent() + .set(&DataKey::Price(asset.clone()), &price); + env.storage() + .persistent() + .set(&DataKey::Timestamp(asset.clone()), &now); + + env.events().publish( + (symbol_short!("setprice"),), + (asset.clone(), price, now), + ); + + Ok(()) + } + + // --------------------------------------------------------------- + // Read – get_price + // --------------------------------------------------------------- + + /// Return the latest recorded price for `asset` in micro-units. + /// + /// Returns `OracleError::AssetNotFound` if no price has ever been + /// pushed for that asset. + pub fn get_price(env: Env, asset: String) -> Result { + env.storage() + .persistent() + .get(&DataKey::Price(asset)) + .ok_or(OracleError::AssetNotFound) + } + + // --------------------------------------------------------------- + // Read – get_timestamp + // --------------------------------------------------------------- + + /// Return the UNIX timestamp of the most recent `set_price` call + /// for `asset`. + /// + /// Returns `OracleError::AssetNotFound` if no price has ever been + /// pushed for that asset. + pub fn get_timestamp(env: Env, asset: String) -> Result { + env.storage() + .persistent() + .get(&DataKey::Timestamp(asset)) + .ok_or(OracleError::AssetNotFound) + } + + // --------------------------------------------------------------- + // Read – is_stale + // --------------------------------------------------------------- + + /// Return `true` when the price for `asset` is older than the + /// configured `stale_ttl` seconds relative to the current ledger + /// timestamp. + /// + /// Returns `OracleError::AssetNotFound` if no price has ever been + /// pushed for that asset. + pub fn is_stale(env: Env, asset: String) -> Result { + let last_ts: u64 = env + .storage() + .persistent() + .get(&DataKey::Timestamp(asset)) + .ok_or(OracleError::AssetNotFound)?; + + let stale_ttl: u64 = env + .storage() + .instance() + .get(&DataKey::StaleTtl) + .unwrap(); + + let now: u64 = env.ledger().timestamp(); + + Ok(now.saturating_sub(last_ts) > stale_ttl) + } + + // --------------------------------------------------------------- + // Read – get_stale_ttl + // --------------------------------------------------------------- + + /// Return the configured staleness TTL in seconds. + pub fn get_stale_ttl(env: Env) -> u64 { + env.storage() + .instance() + .get(&DataKey::StaleTtl) + .unwrap() + } +} + +// ------------------------------------------------------------------- +// Unit tests +// ------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + use soroban_sdk::{ + testutils::{Address as _, Ledger}, + Address, Env, + }; + + /// Helper: create a fresh test environment with all auth mocked. + fn setup() -> (Env, Address, Address) { + let env = Env::default(); + env.mock_all_auths(); + let admin = Address::generate(&env); + let contract_id = env.register(OraclePriceFeed, ()); + (env, admin, contract_id) + } + + #[test] + fn test_initialize_and_set_get_price() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "XLM"); + client.set_price(&asset, &1_100_000i128); + + let price = client.get_price(&asset); + assert_eq!(price, 1_100_000i128); + } + + #[test] + fn test_price_not_stale_immediately_after_update() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "BTC"); + env.ledger().with_mut(|l| l.timestamp = 1_000); + client.set_price(&asset, &40_000_000_000i128); + + // Still within TTL – should not be stale. + assert!(!client.is_stale(&asset)); + } + + #[test] + fn test_price_becomes_stale_after_ttl() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "ETH"); + env.ledger().with_mut(|l| l.timestamp = 1_000); + client.set_price(&asset, &2_000_000_000i128); + + // Advance ledger by more than the 300-second TTL. + env.ledger().with_mut(|l| l.timestamp = 1_500); + assert!(client.is_stale(&asset)); + } + + #[test] + fn test_update_price_refreshes_staleness() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "XLM"); + env.ledger().with_mut(|l| l.timestamp = 1_000); + client.set_price(&asset, &1_000_000i128); + + // Go past staleness threshold. + env.ledger().with_mut(|l| l.timestamp = 2_000); + assert!(client.is_stale(&asset)); + + // Push a fresh price – staleness should reset. + client.set_price(&asset, &1_050_000i128); + assert!(!client.is_stale(&asset)); + + let price = client.get_price(&asset); + assert_eq!(price, 1_050_000i128); + } + + #[test] + fn test_get_timestamp() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "XLM"); + env.ledger().with_mut(|l| l.timestamp = 5_000); + client.set_price(&asset, &1_000_000i128); + + assert_eq!(client.get_timestamp(&asset), 5_000u64); + } + + #[test] + fn test_asset_not_found_panics_via_try() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "UNKNOWN"); + // Contract returns Err(AssetNotFound); try_ yields Err(Ok(AssetNotFound)) + let result = client.try_get_price(&asset); + assert_eq!(result, Err(Ok(OracleError::AssetNotFound))); + } + + #[test] + fn test_double_initialize_fails() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + let result = client.try_initialize(&admin, &300u64); + // Contract returns Err(AlreadyInitialized); try_initialize yields Err(Ok(AlreadyInitialized)) + assert_eq!(result, Err(Ok(OracleError::AlreadyInitialized))); + } + + #[test] + fn test_invalid_price_rejected() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &300u64); + + let asset = String::from_str(&env, "XLM"); + + let result_zero = client.try_set_price(&asset, &0i128); + // Contract returns Err(InvalidPrice) + assert_eq!(result_zero, Err(Ok(OracleError::InvalidPrice))); + + let result_neg = client.try_set_price(&asset, &-1i128); + assert_eq!(result_neg, Err(Ok(OracleError::InvalidPrice))); + } + + #[test] + fn test_get_stale_ttl() { + let (env, admin, contract_id) = setup(); + let client = OraclePriceFeedClient::new(&env, &contract_id); + + client.initialize(&admin, &600u64); + assert_eq!(client.get_stale_ttl(), 600u64); + } +} diff --git a/examples/contracts/oracle/test_snapshots/tests/test_asset_not_found_panics_via_try.1.json b/examples/contracts/oracle/test_snapshots/tests/test_asset_not_found_panics_via_try.1.json new file mode 100644 index 0000000..066896e --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_asset_not_found_panics_via_try.1.json @@ -0,0 +1,156 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_double_initialize_fails.1.json b/examples/contracts/oracle/test_snapshots/tests/test_double_initialize_fails.1.json new file mode 100644 index 0000000..066896e --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_double_initialize_fails.1.json @@ -0,0 +1,156 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_get_stale_ttl.1.json b/examples/contracts/oracle/test_snapshots/tests/test_get_stale_ttl.1.json new file mode 100644 index 0000000..e9235d2 --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_get_stale_ttl.1.json @@ -0,0 +1,156 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 600 + } + ] + } + }, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 600 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_get_timestamp.1.json b/examples/contracts/oracle/test_snapshots/tests/test_get_timestamp.1.json new file mode 100644 index 0000000..30d076b --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_get_timestamp.1.json @@ -0,0 +1,307 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 300 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "XLM" + }, + { + "i128": { + "hi": 0, + "lo": 1000000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 5000, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "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": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent", + "val": { + "i128": { + "hi": 0, + "lo": 1000000 + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent", + "val": { + "u64": 5000 + } + } + }, + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_initialize_and_set_get_price.1.json b/examples/contracts/oracle/test_snapshots/tests/test_initialize_and_set_get_price.1.json new file mode 100644 index 0000000..9a0ad01 --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_initialize_and_set_get_price.1.json @@ -0,0 +1,307 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 300 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "XLM" + }, + { + "i128": { + "hi": 0, + "lo": 1100000 + } + } + ] + } + }, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "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": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent", + "val": { + "i128": { + "hi": 0, + "lo": 1100000 + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_invalid_price_rejected.1.json b/examples/contracts/oracle/test_snapshots/tests/test_invalid_price_rejected.1.json new file mode 100644 index 0000000..0b26ecf --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_invalid_price_rejected.1.json @@ -0,0 +1,157 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_price_becomes_stale_after_ttl.1.json b/examples/contracts/oracle/test_snapshots/tests/test_price_becomes_stale_after_ttl.1.json new file mode 100644 index 0000000..23f5ce2 --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_price_becomes_stale_after_ttl.1.json @@ -0,0 +1,307 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 300 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "ETH" + }, + { + "i128": { + "hi": 0, + "lo": 2000000000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 1500, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "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": "Price" + }, + { + "string": "ETH" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Price" + }, + { + "string": "ETH" + } + ] + }, + "durability": "persistent", + "val": { + "i128": { + "hi": 0, + "lo": 2000000000 + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "ETH" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "ETH" + } + ] + }, + "durability": "persistent", + "val": { + "u64": 1000 + } + } + }, + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_price_not_stale_immediately_after_update.1.json b/examples/contracts/oracle/test_snapshots/tests/test_price_not_stale_immediately_after_update.1.json new file mode 100644 index 0000000..bad88e8 --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_price_not_stale_immediately_after_update.1.json @@ -0,0 +1,307 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 300 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "BTC" + }, + { + "i128": { + "hi": 0, + "lo": 40000000000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 1000, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "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": "Price" + }, + { + "string": "BTC" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Price" + }, + { + "string": "BTC" + } + ] + }, + "durability": "persistent", + "val": { + "i128": { + "hi": 0, + "lo": 40000000000 + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "BTC" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "BTC" + } + ] + }, + "durability": "persistent", + "val": { + "u64": 1000 + } + } + }, + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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/examples/contracts/oracle/test_snapshots/tests/test_update_price_refreshes_staleness.1.json b/examples/contracts/oracle/test_snapshots/tests/test_update_price_refreshes_staleness.1.json new file mode 100644 index 0000000..38d88ae --- /dev/null +++ b/examples/contracts/oracle/test_snapshots/tests/test_update_price_refreshes_staleness.1.json @@ -0,0 +1,367 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "u64": 300 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "XLM" + }, + { + "i128": { + "hi": 0, + "lo": 1000000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "set_price", + "args": [ + { + "string": "XLM" + }, + { + "i128": { + "hi": 0, + "lo": 1050000 + } + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 2000, + "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": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "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": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Price" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent", + "val": { + "i128": { + "hi": 0, + "lo": 1050000 + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "vec": [ + { + "symbol": "Timestamp" + }, + { + "string": "XLM" + } + ] + }, + "durability": "persistent", + "val": { + "u64": 2000 + } + } + }, + "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" + } + }, + { + "key": { + "vec": [ + { + "symbol": "StaleTtl" + } + ] + }, + "val": { + "u64": 300 + } + } + ] + } + } + } + }, + "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