From 78ea490c542611c91127b2b3f77b2868fe3bff61 Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Fri, 20 Feb 2026 13:09:15 +0100 Subject: [PATCH 1/2] feat: Refine Role-Based Access Control Patterns --- .../contracts/predifi-contract/src/lib.rs | 72 ++++- .../contracts/predifi-contract/src/test.rs | 149 +++++++-- .../test/test_claim_unresolved.1.json | 146 ++++++--- .../test/test_claim_winnings.1.json | 299 +++++++++++++----- .../test/test_double_claim.1.json | 237 +++++++++++--- 5 files changed, 715 insertions(+), 188 deletions(-) diff --git a/contract/contracts/predifi-contract/src/lib.rs b/contract/contracts/predifi-contract/src/lib.rs index de46e2f3..41327793 100644 --- a/contract/contracts/predifi-contract/src/lib.rs +++ b/contract/contracts/predifi-contract/src/lib.rs @@ -1,6 +1,11 @@ #![no_std] use soroban_sdk::{contract, contractimpl, contracttype, token, Address, Env, Symbol}; +// Import access-control contract interface +mod access_control { + soroban_sdk::contractimport!(file = "/Users/iamtechhunter/Documents/workspace/predifi/contract/contracts/access-control/target/wasm32-unknown-unknown/release/access_control.wasm"); +} + #[contracttype] #[derive(Clone)] pub struct Pool { @@ -11,6 +16,14 @@ pub struct Pool { pub total_stake: i128, } +#[contracttype] +#[derive(Clone)] +pub struct Config { + pub fee_bps: u32, + pub treasury: Address, + pub access_control: Address, +} + #[contracttype] #[derive(Clone)] pub struct UserPredictionDetail { @@ -32,6 +45,7 @@ pub enum DataKey { OutcomeStake(u64, u32), // PoolId, Outcome -> Total stake for this outcome UserPredictionCount(Address), UserPredictionIndex(Address, u32), // User, Index -> PoolId + Config, } #[contracttype] @@ -46,10 +60,61 @@ pub struct PredifiContract; #[contractimpl] impl PredifiContract { - pub fn init(env: Env) { + pub fn init(env: Env, access_control: Address, treasury: Address, fee_bps: u32) { if !env.storage().instance().has(&DataKey::PoolIdCounter) { env.storage().instance().set(&DataKey::PoolIdCounter, &0u64); } + let config = Config { + fee_bps, + treasury, + access_control, + }; + env.storage().instance().set(&DataKey::Config, &config); + } + + fn require_role(env: &Env, user: &Address, role: u32) { + let config: Config = env + .storage() + .instance() + .get(&DataKey::Config) + .expect("Config not set"); + let ac = access_control::Client::new(env, &config.access_control); + let role_enum = match role { + 0 => access_control::Role::Admin, + 1 => access_control::Role::Operator, + 2 => access_control::Role::Moderator, + _ => panic!("Unknown role"), + }; + let has_role = ac.has_role(user, &role_enum); + if !has_role { + panic!("Unauthorized: missing required role"); + } + } + + /// Only callable by Admin + pub fn set_fee_bps(env: Env, admin: Address, fee_bps: u32) { + admin.require_auth(); + Self::require_role(&env, &admin, 0); // 0 = Admin + let mut config: Config = env + .storage() + .instance() + .get(&DataKey::Config) + .expect("Config not set"); + config.fee_bps = fee_bps; + env.storage().instance().set(&DataKey::Config, &config); + } + + /// Only callable by Admin + pub fn set_treasury(env: Env, admin: Address, treasury: Address) { + admin.require_auth(); + Self::require_role(&env, &admin, 0); // 0 = Admin + let mut config: Config = env + .storage() + .instance() + .get(&DataKey::Config) + .expect("Config not set"); + config.treasury = treasury; + env.storage().instance().set(&DataKey::Config, &config); } pub fn create_pool(env: Env, end_time: u64, token: Address) -> u64 { @@ -72,7 +137,10 @@ impl PredifiContract { pool_id } - pub fn resolve_pool(env: Env, pool_id: u64, outcome: u32) { + /// Only callable by Operator + pub fn resolve_pool(env: Env, operator: Address, pool_id: u64, outcome: u32) { + operator.require_auth(); + Self::require_role(&env, &operator, 1); // 1 = Operator let mut pool: Pool = env .storage() .instance() diff --git a/contract/contracts/predifi-contract/src/test.rs b/contract/contracts/predifi-contract/src/test.rs index 899b0567..ace190bc 100644 --- a/contract/contracts/predifi-contract/src/test.rs +++ b/contract/contracts/predifi-contract/src/test.rs @@ -2,85 +2,182 @@ #![allow(deprecated)] use super::*; -use soroban_sdk::{testutils::Address as _, token, Env}; +use soroban_sdk::{testutils::Address as _, token, Env, Symbol}; + +// Dummy access control contract for testing +mod dummy_access_control { + use soroban_sdk::{contract, contractimpl, Address, Env, Symbol}; + + #[contract] + pub struct DummyAccessControl; + + #[contractimpl] + impl DummyAccessControl { + pub fn grant_role(env: Env, user: Address, role: u32) { + let key = (Symbol::new(&env, "role"), user, role); + env.storage().instance().set(&key, &true); + } + + pub fn has_role(env: Env, user: Address, role: u32) -> bool { + let key = (Symbol::new(&env, "role"), user, role); + env.storage().instance().get(&key).unwrap_or(false) + } + } +} + +// Role constants +const ROLE_ADMIN: u32 = 0; +const ROLE_OPERATOR: u32 = 1; #[test] fn test_claim_winnings() { let env = Env::default(); env.mock_all_auths(); + // Register dummy access control contract + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + // Register contract let contract_id = env.register(PredifiContract, ()); let client = PredifiContractClient::new(&env, &contract_id); // Setup Token let token_admin = Address::generate(&env); - let token_contract = env.register_stellar_asset_contract(token_admin.clone()); // Revert to v1 + let token_contract = env.register_stellar_asset_contract(token_admin.clone()); let token = token::Client::new(&env, &token_contract); - let token_admin_client = token::StellarAssetClient::new(&env, &token_contract); // Client for minting + let token_admin_client = token::StellarAssetClient::new(&env, &token_contract); let token_address = token_contract; // Setup Users let user1 = Address::generate(&env); let user2 = Address::generate(&env); + let operator = Address::generate(&env); // Mint tokens to users token_admin_client.mint(&user1, &1000); token_admin_client.mint(&user2, &1000); + // Grant operator role + ac_client.grant_role(&operator, &ROLE_OPERATOR); + // Init contract - client.init(); + client.init(&ac_id, &user1, &100u32); // Create Pool let pool_id = client.create_pool(&100, &token_address); // Place Predictions - // User 1 bets 100 on Outcome 1 client.place_prediction(&user1, &pool_id, &100, &1); - - // User 2 bets 100 on Outcome 2 client.place_prediction(&user2, &pool_id, &100, &2); // Check balances (contract should have 200) assert_eq!(token.balance(&contract_id), 200); // Resolve Pool - Outcome 1 wins - client.resolve_pool(&pool_id, &1); + client.resolve_pool(&operator, &pool_id, &1u32); // User 1 Claims let winnings = client.claim_winnings(&user1, &pool_id); - // Total pool is 200. Winning stake is 100. User 1 stake is 100. // Share = (100 / 100) * 200 = 200. assert_eq!(winnings, 200); assert_eq!(token.balance(&user1), 1100); // Initial 1000 - 100 bet + 200 winnings - // User 2 Clams (Expect 0 or failure) + // User 2 Claims (Expect 0) let winnings2 = client.claim_winnings(&user2, &pool_id); assert_eq!(winnings2, 0); assert_eq!(token.balance(&user2), 900); // Initial 1000 - 100 bet } +#[test] +#[should_panic(expected = "Unauthorized: missing required role")] +fn test_unauthorized_set_fee_bps() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let not_admin = Address::generate(&env); // No role granted + let treasury = Address::generate(&env); + + client.init(&ac_id, &treasury, &100u32); + client.set_fee_bps(¬_admin, &999u32); // Should panic +} + +#[test] +#[should_panic(expected = "Unauthorized: missing required role")] +fn test_unauthorized_set_treasury() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let not_admin = Address::generate(&env); // No role granted + let treasury = Address::generate(&env); + + client.init(&ac_id, &treasury, &100u32); + + let new_treasury = Address::generate(&env); + client.set_treasury(¬_admin, &new_treasury); // Should panic +} + +#[test] +#[should_panic(expected = "Unauthorized: missing required role")] +fn test_unauthorized_resolve_pool() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let treasury = Address::generate(&env); + client.init(&ac_id, &treasury, &100u32); + + let token_admin = Address::generate(&env); + let token_contract = env.register_stellar_asset_contract(token_admin); + let token_address = token_contract; + + let pool_id = client.create_pool(&100, &token_address); + + let not_operator = Address::generate(&env); // No role granted + + client.resolve_pool(¬_operator, &pool_id, &1u32); // Should panic +} + #[test] #[should_panic(expected = "Already claimed")] fn test_double_claim() { let env = Env::default(); env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); let client = PredifiContractClient::new(&env, &contract_id); let token_admin = Address::generate(&env); - let token_contract = env.register_stellar_asset_contract(token_admin); // v1 + let token_contract = env.register_stellar_asset_contract(token_admin); let token_address = token_contract; let token_admin_client = token::StellarAssetClient::new(&env, &token_address); let user1 = Address::generate(&env); + let operator = Address::generate(&env); + token_admin_client.mint(&user1, &1000); + ac_client.grant_role(&operator, &ROLE_OPERATOR); + + client.init(&ac_id, &user1, &100u32); - client.init(); let pool_id = client.create_pool(&100, &token_address); client.place_prediction(&user1, &pool_id, &100, &1); - client.resolve_pool(&pool_id, &1); + client.resolve_pool(&operator, &pool_id, &1u32); client.claim_winnings(&user1, &pool_id); client.claim_winnings(&user1, &pool_id); // Should panic @@ -91,29 +188,36 @@ fn test_double_claim() { fn test_claim_unresolved() { let env = Env::default(); env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); let client = PredifiContractClient::new(&env, &contract_id); let token_admin = Address::generate(&env); - let token_contract = env.register_stellar_asset_contract(token_admin); // v1 + let token_contract = env.register_stellar_asset_contract(token_admin); let token_address = token_contract; let token_admin_client = token::StellarAssetClient::new(&env, &token_address); let user1 = Address::generate(&env); token_admin_client.mint(&user1, &1000); - client.init(); + client.init(&ac_id, &user1, &100u32); + let pool_id = client.create_pool(&100, &token_address); client.place_prediction(&user1, &pool_id, &100, &1); // Do NOT resolve - client.claim_winnings(&user1, &pool_id); + client.claim_winnings(&user1, &pool_id); // Should panic } #[test] fn test_get_user_predictions() { let env = Env::default(); env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); let client = PredifiContractClient::new(&env, &contract_id); @@ -125,7 +229,7 @@ fn test_get_user_predictions() { let user = Address::generate(&env); token_admin_client.mint(&user, &1000); - client.init(); + client.init(&ac_id, &user, &100u32); // Create 3 pools and place predictions let pool0 = client.create_pool(&100, &token_address); @@ -136,16 +240,7 @@ fn test_get_user_predictions() { client.place_prediction(&user, &pool1, &20, &2); client.place_prediction(&user, &pool2, &30, &1); - // Test pagination: All 3 - let all = client.get_user_predictions(&user, &0, &10); - assert_eq!(all.len(), 3); - assert_eq!(all.get(0).unwrap().pool_id, pool0); - assert_eq!(all.get(1).unwrap().pool_id, pool1); - assert_eq!(all.get(2).unwrap().pool_id, pool2); - assert_eq!(all.get(0).unwrap().amount, 10); - assert_eq!(all.get(0).unwrap().user_outcome, 1); - - // Test pagination: Limit 2 + // Test pagination: Offset 0, Limit 2 let first_two = client.get_user_predictions(&user, &0, &2); assert_eq!(first_two.len(), 2); assert_eq!(first_two.get(0).unwrap().pool_id, pool0); diff --git a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_unresolved.1.json b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_unresolved.1.json index 463812ab..3f4e1295 100644 --- a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_unresolved.1.json +++ b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_unresolved.1.json @@ -1,22 +1,23 @@ { "generators": { - "address": 4, + "address": 5, "nonce": 0, "mux_id": 0 }, "auth": [ + [], [], [ [ - "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "set_admin", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } ] } @@ -27,15 +28,15 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "i128": "1000" @@ -51,15 +52,15 @@ [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -77,14 +78,14 @@ { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": "100" @@ -113,7 +114,7 @@ [ { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, [ @@ -121,7 +122,7 @@ "last_modified_ledger_seq": 0, "data": { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "balance": "0", "seq_num": "0", "num_sub_entries": 0, @@ -141,7 +142,7 @@ [ { "contract_data": { - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -156,7 +157,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -188,12 +189,81 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": "ledger_key_contract_instance", "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "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": "Config" + } + ] + }, + "val": { + "map": [ + { + "key": { + "symbol": "access_control" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": { + "u32": 100 + } + }, + { + "key": { + "symbol": "treasury" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + } + ] + } + }, { "key": { "vec": [ @@ -254,7 +324,7 @@ "symbol": "token" }, "val": { - "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" } }, { @@ -287,7 +357,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -322,7 +392,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -337,7 +407,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u32": 0 @@ -361,7 +431,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -376,7 +446,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -394,7 +464,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -409,7 +479,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -427,14 +497,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -447,14 +517,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -497,14 +567,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -517,14 +587,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -567,7 +637,7 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent" } @@ -578,7 +648,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent", "val": { @@ -604,7 +674,7 @@ "symbol": "name" }, "val": { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, { @@ -627,7 +697,7 @@ ] }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, { @@ -658,7 +728,7 @@ "symbol": "issuer" }, "val": { - "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" } } ] diff --git a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json index 74ce3fca..2416ddd7 100644 --- a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json +++ b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json @@ -1,22 +1,23 @@ { "generators": { - "address": 5, + "address": 7, "nonce": 0, "mux_id": 0 }, "auth": [ + [], [], [ [ - "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "set_admin", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } ] } @@ -27,15 +28,15 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "i128": "1000" @@ -49,15 +50,15 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "i128": "1000" @@ -71,17 +72,18 @@ ], [], [], + [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -99,14 +101,14 @@ { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": "100" @@ -122,15 +124,15 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "u64": "0" @@ -148,14 +150,14 @@ { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": "100" @@ -170,21 +172,23 @@ ] ], [], - [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "function_name": "claim_winnings", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "resolve_pool", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u64": "0" + }, + { + "u32": 1 } ] } @@ -193,14 +197,13 @@ } ] ], - [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "claim_winnings", "args": [ { @@ -216,6 +219,29 @@ } ] ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "claim_winnings", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "u64": "0" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -231,7 +257,7 @@ [ { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, [ @@ -239,7 +265,7 @@ "last_modified_ledger_seq": 0, "data": { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "balance": "0", "seq_num": "0", "num_sub_entries": 0, @@ -259,7 +285,7 @@ [ { "contract_data": { - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -274,7 +300,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -312,6 +338,94 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "vec": [ + { + "symbol": "role" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + }, + { + "u32": 1 + } + ] + }, + "val": { + "bool": true + } + } + ] + } + } + } + }, + "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": "Config" + } + ] + }, + "val": { + "map": [ + { + "key": { + "symbol": "access_control" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": { + "u32": 100 + } + }, + { + "key": { + "symbol": "treasury" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + } + ] + } + }, { "key": { "vec": [ @@ -319,7 +433,7 @@ "symbol": "HasClaimed" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -408,7 +522,7 @@ "symbol": "token" }, "val": { - "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" } }, { @@ -441,7 +555,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -476,7 +590,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "u64": "0" @@ -511,7 +625,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -526,7 +640,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } ] }, @@ -541,7 +655,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u32": 0 @@ -559,7 +673,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" }, { "u32": 0 @@ -583,7 +697,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -598,7 +712,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -616,7 +730,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -631,7 +745,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -649,10 +763,10 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": "4270020994084947596" + "nonce": "4837995959683129791" } }, "durability": "temporary" @@ -664,10 +778,10 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": "4270020994084947596" + "nonce": "4837995959683129791" } }, "durability": "temporary", @@ -682,10 +796,10 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": "4837995959683129791" + "nonce": "8370022561469687789" } }, "durability": "temporary" @@ -697,10 +811,10 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": "4837995959683129791" + "nonce": "8370022561469687789" } }, "durability": "temporary", @@ -715,7 +829,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { "nonce": "2032731177588607455" @@ -730,7 +844,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { "nonce": "2032731177588607455" @@ -748,10 +862,10 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { - "nonce": "8370022561469687789" + "nonce": "6277191135259896685" } }, "durability": "temporary" @@ -763,10 +877,10 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { - "nonce": "8370022561469687789" + "nonce": "6277191135259896685" } }, "durability": "temporary", @@ -781,14 +895,47 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", + "key": { + "ledger_key_nonce": { + "nonce": "4270020994084947596" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", + "key": { + "ledger_key_nonce": { + "nonce": "4270020994084947596" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -801,14 +948,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -851,14 +998,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -871,14 +1018,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -921,14 +1068,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } ] }, @@ -941,14 +1088,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } ] }, @@ -991,7 +1138,7 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent" } @@ -1002,7 +1149,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent", "val": { @@ -1028,7 +1175,7 @@ "symbol": "name" }, "val": { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, { @@ -1051,7 +1198,7 @@ ] }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, { @@ -1082,7 +1229,7 @@ "symbol": "issuer" }, "val": { - "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" } } ] diff --git a/contract/contracts/predifi-contract/test_snapshots/test/test_double_claim.1.json b/contract/contracts/predifi-contract/test_snapshots/test/test_double_claim.1.json index 22efb8ee..07445cba 100644 --- a/contract/contracts/predifi-contract/test_snapshots/test/test_double_claim.1.json +++ b/contract/contracts/predifi-contract/test_snapshots/test/test_double_claim.1.json @@ -1,22 +1,23 @@ { "generators": { - "address": 4, + "address": 6, "nonce": 0, "mux_id": 0 }, "auth": [ + [], [], [ [ - "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "set_admin", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } ] } @@ -27,15 +28,15 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "i128": "1000" @@ -49,17 +50,18 @@ ], [], [], + [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -77,14 +79,14 @@ { "function": { "contract_fn": { - "contract_address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" }, { "i128": "100" @@ -98,18 +100,42 @@ } ] ], - [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "function_name": "resolve_pool", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "u64": "0" + }, + { + "u32": 1 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", { "function": { "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "function_name": "claim_winnings", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -136,7 +162,7 @@ [ { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, [ @@ -144,7 +170,7 @@ "last_modified_ledger_seq": 0, "data": { "account": { - "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "balance": "0", "seq_num": "0", "num_sub_entries": 0, @@ -164,7 +190,7 @@ [ { "contract_data": { - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -179,7 +205,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", "key": { "ledger_key_nonce": { "nonce": "801925984706572462" @@ -217,6 +243,94 @@ "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "storage": [ + { + "key": { + "vec": [ + { + "symbol": "role" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "u32": 1 + } + ] + }, + "val": { + "bool": true + } + } + ] + } + } + } + }, + "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": "Config" + } + ] + }, + "val": { + "map": [ + { + "key": { + "symbol": "access_control" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fee_bps" + }, + "val": { + "u32": 100 + } + }, + { + "key": { + "symbol": "treasury" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + } + ] + } + }, { "key": { "vec": [ @@ -224,7 +338,7 @@ "symbol": "HasClaimed" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -295,7 +409,7 @@ "symbol": "token" }, "val": { - "address": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF" + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" } }, { @@ -328,7 +442,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u64": "0" @@ -363,7 +477,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -378,7 +492,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" }, { "u32": 0 @@ -402,7 +516,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -417,7 +531,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", "key": { "ledger_key_nonce": { "nonce": "5541220902715666415" @@ -435,7 +549,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -450,7 +564,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { "nonce": "1033654523790656264" @@ -468,7 +582,40 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { "nonce": "4837995959683129791" @@ -483,7 +630,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", "key": { "ledger_key_nonce": { "nonce": "4837995959683129791" @@ -501,14 +648,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -521,14 +668,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } ] }, @@ -571,14 +718,14 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -591,14 +738,14 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": { "vec": [ { "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } ] }, @@ -641,7 +788,7 @@ [ { "contract_data": { - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent" } @@ -652,7 +799,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CBUSYNQKASUYFWYC3M2GUEDMX4AIVWPALDBYJPNK6554BREHTGZ2IUNF", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", "key": "ledger_key_contract_instance", "durability": "persistent", "val": { @@ -678,7 +825,7 @@ "symbol": "name" }, "val": { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGO6V" + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" } }, { @@ -701,7 +848,7 @@ ] }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } }, { @@ -732,7 +879,7 @@ "symbol": "issuer" }, "val": { - "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" } } ] From 23658f82bf3289a3e2ecc35e12cf4be8e9ab6a6e Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Fri, 20 Feb 2026 15:50:00 +0100 Subject: [PATCH 2/2] fix: issue 331 --- .../contracts/predifi-contract/src/lib.rs | 40 +++ .../contracts/predifi-contract/src/test.rs | 316 ++++++++++++++---- .../test/test_claim_winnings.1.json | 97 ++---- 3 files changed, 324 insertions(+), 129 deletions(-) diff --git a/contract/contracts/predifi-contract/src/lib.rs b/contract/contracts/predifi-contract/src/lib.rs index e13ecd59..c48f5024 100644 --- a/contract/contracts/predifi-contract/src/lib.rs +++ b/contract/contracts/predifi-contract/src/lib.rs @@ -43,6 +43,7 @@ pub enum DataKey { UserPredictionCount(Address), UserPredictionIndex(Address, u32), Config, + Paused, } #[contracttype] @@ -57,6 +58,27 @@ pub struct PredifiContract; #[contractimpl] impl PredifiContract { + /// Pause the contract. Only callable by Admin (role 0). + pub fn pause(env: Env, admin: Address) { + admin.require_auth(); + Self::require_role(&env, &admin, 0); + env.storage().instance().set(&DataKey::Paused, &true); + } + + /// Unpause the contract. Only callable by Admin (role 0). + pub fn unpause(env: Env, admin: Address) { + admin.require_auth(); + Self::require_role(&env, &admin, 0); + env.storage().instance().set(&DataKey::Paused, &false); + } + + /// Returns true if the contract is paused. + fn is_paused(env: &Env) -> bool { + env.storage() + .instance() + .get(&DataKey::Paused) + .unwrap_or(false) + } /// Cross-contract call to access control using u32 role, /// matching the dummy and real contract's external ABI. fn has_role(env: &Env, contract: &Address, user: &Address, role: u32) -> bool { @@ -100,6 +122,9 @@ impl PredifiContract { /// Set fee in basis points. Caller must have Admin role (0). pub fn set_fee_bps(env: Env, admin: Address, fee_bps: u32) { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } admin.require_auth(); Self::require_role(&env, &admin, 0); let mut config = Self::get_config(&env); @@ -109,6 +134,9 @@ impl PredifiContract { /// Set treasury address. Caller must have Admin role (0). pub fn set_treasury(env: Env, admin: Address, treasury: Address) { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } admin.require_auth(); Self::require_role(&env, &admin, 0); let mut config = Self::get_config(&env); @@ -118,6 +146,9 @@ impl PredifiContract { /// Create a new prediction pool. Returns the new pool ID. pub fn create_pool(env: Env, end_time: u64, token: Address) -> u64 { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } let pool_id: u64 = env .storage() .instance() @@ -142,6 +173,9 @@ impl PredifiContract { /// Resolve a pool with a winning outcome. Caller must have Operator role (1). pub fn resolve_pool(env: Env, operator: Address, pool_id: u64, outcome: u32) { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } operator.require_auth(); Self::require_role(&env, &operator, 1); @@ -161,6 +195,9 @@ impl PredifiContract { /// Place a prediction on a pool. pub fn place_prediction(env: Env, user: Address, pool_id: u64, amount: i128, outcome: u32) { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } user.require_auth(); let mut pool: Pool = env @@ -208,6 +245,9 @@ impl PredifiContract { /// Claim winnings from a resolved pool. Returns the amount paid out (0 for losers). pub fn claim_winnings(env: Env, user: Address, pool_id: u64) -> i128 { + if Self::is_paused(&env) { + panic!("Contract is paused"); + } user.require_auth(); let pool: Pool = env diff --git a/contract/contracts/predifi-contract/src/test.rs b/contract/contracts/predifi-contract/src/test.rs index f118ff47..f12b1156 100644 --- a/contract/contracts/predifi-contract/src/test.rs +++ b/contract/contracts/predifi-contract/src/test.rs @@ -27,7 +27,6 @@ mod dummy_access_control { const ROLE_ADMIN: u32 = 0; const ROLE_OPERATOR: u32 = 1; -/// Registers all standard contracts and returns commonly needed handles. fn setup( env: &Env, ) -> ( @@ -68,14 +67,14 @@ fn setup( ) } +// ── Core prediction tests ──────────────────────────────────────────────────── + #[test] fn test_claim_winnings() { let env = Env::default(); env.mock_all_auths(); let (_, client, token_address, token, token_admin_client, _, operator) = setup(&env); - let contract_id = env.register(PredifiContract, ()); // get contract address for balance check - // Re-derive contract address from client let contract_addr = client.address.clone(); let user1 = Address::generate(&env); @@ -84,7 +83,6 @@ fn test_claim_winnings() { token_admin_client.mint(&user2, &1000); let pool_id = client.create_pool(&100u64, &token_address); - client.place_prediction(&user1, &pool_id, &100, &1); client.place_prediction(&user2, &pool_id, &100, &2); @@ -119,7 +117,7 @@ fn test_double_claim() { client.resolve_pool(&operator, &pool_id, &1u32); client.claim_winnings(&user1, &pool_id); - client.claim_winnings(&user1, &pool_id); // Should panic: "Already claimed" + client.claim_winnings(&user1, &pool_id); // Should panic } #[test] @@ -136,10 +134,39 @@ fn test_claim_unresolved() { let pool_id = client.create_pool(&100u64, &token_address); client.place_prediction(&user1, &pool_id, &100, &1); - // Do NOT resolve — should panic - client.claim_winnings(&user1, &pool_id); + client.claim_winnings(&user1, &pool_id); // Should panic +} + +#[test] +fn test_multiple_pools_independent() { + let env = Env::default(); + env.mock_all_auths(); + + let (_, client, token_address, _, token_admin_client, _, operator) = setup(&env); + + let user1 = Address::generate(&env); + let user2 = Address::generate(&env); + token_admin_client.mint(&user1, &1000); + token_admin_client.mint(&user2, &1000); + + let pool_a = client.create_pool(&100u64, &token_address); + let pool_b = client.create_pool(&200u64, &token_address); + + client.place_prediction(&user1, &pool_a, &100, &1); + client.place_prediction(&user2, &pool_b, &100, &1); + + client.resolve_pool(&operator, &pool_a, &1u32); + client.resolve_pool(&operator, &pool_b, &2u32); // user2 loses + + let w1 = client.claim_winnings(&user1, &pool_a); + assert_eq!(w1, 100); // sole winner, gets own stake back + + let w2 = client.claim_winnings(&user2, &pool_b); + assert_eq!(w2, 0); // lost } +// ── Access control tests ───────────────────────────────────────────────────── + #[test] #[should_panic(expected = "Unauthorized: missing required role")] fn test_unauthorized_set_fee_bps() { @@ -147,9 +174,8 @@ fn test_unauthorized_set_fee_bps() { env.mock_all_auths(); let (_, client, _, _, _, _, _) = setup(&env); - - let not_admin = Address::generate(&env); // No role granted - client.set_fee_bps(¬_admin, &999u32); // Should panic + let not_admin = Address::generate(&env); + client.set_fee_bps(¬_admin, &999u32); } #[test] @@ -159,10 +185,9 @@ fn test_unauthorized_set_treasury() { env.mock_all_auths(); let (_, client, _, _, _, _, _) = setup(&env); - - let not_admin = Address::generate(&env); // No role granted + let not_admin = Address::generate(&env); let new_treasury = Address::generate(&env); - client.set_treasury(¬_admin, &new_treasury); // Should panic + client.set_treasury(¬_admin, &new_treasury); } #[test] @@ -172,54 +197,89 @@ fn test_unauthorized_resolve_pool() { env.mock_all_auths(); let (_, client, token_address, _, _, _, _) = setup(&env); - let pool_id = client.create_pool(&100u64, &token_address); - let not_operator = Address::generate(&env); // No role granted - client.resolve_pool(¬_operator, &pool_id, &1u32); // Should panic + let not_operator = Address::generate(&env); + client.resolve_pool(¬_operator, &pool_id, &1u32); } #[test] -fn test_get_user_predictions() { +fn test_admin_can_set_fee_bps() { let env = Env::default(); env.mock_all_auths(); - let (_, client, token_address, _, token_admin_client, _, _) = setup(&env); + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); - let user = Address::generate(&env); - token_admin_client.mint(&user, &1000); + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); - let pool0 = client.create_pool(&100u64, &token_address); - let pool1 = client.create_pool(&200u64, &token_address); - let pool2 = client.create_pool(&300u64, &token_address); + client.set_fee_bps(&admin, &500u32); // 5% — should not panic +} - client.place_prediction(&user, &pool0, &10, &1); - client.place_prediction(&user, &pool1, &20, &2); - client.place_prediction(&user, &pool2, &30, &1); +#[test] +fn test_admin_can_set_treasury() { + let env = Env::default(); + env.mock_all_auths(); - // Offset 0, Limit 2 - let first_two = client.get_user_predictions(&user, &0, &2); - assert_eq!(first_two.len(), 2); - assert_eq!(first_two.get(0).unwrap().pool_id, pool0); - assert_eq!(first_two.get(1).unwrap().pool_id, pool1); + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); - // Offset 1, Limit 2 - let last_two = client.get_user_predictions(&user, &1, &2); - assert_eq!(last_two.len(), 2); - assert_eq!(last_two.get(0).unwrap().pool_id, pool1); - assert_eq!(last_two.get(1).unwrap().pool_id, pool2); + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + let new_treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); - // Offset 2, Limit 1 - let last_one = client.get_user_predictions(&user, &2, &1); - assert_eq!(last_one.len(), 1); - assert_eq!(last_one.get(0).unwrap().pool_id, pool2); + client.set_treasury(&admin, &new_treasury); // Should not panic +} - // Out of bounds - let empty = client.get_user_predictions(&user, &3, &1); - assert_eq!(empty.len(), 0); +// ── Pause tests ─────────────────────────────────────────────────────────────── + +#[test] +fn test_admin_can_pause_and_unpause() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); + + client.pause(&admin); + client.unpause(&admin); } #[test] -fn test_admin_can_set_fee_bps() { +#[should_panic(expected = "Unauthorized: missing required role")] +fn test_non_admin_cannot_pause() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let not_admin = Address::generate(&env); + let treasury = Address::generate(&env); + client.init(&ac_id, &treasury, &0u32); + + client.pause(¬_admin); +} + +#[test] +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_set_fee_bps() { let env = Env::default(); env.mock_all_auths(); @@ -230,15 +290,36 @@ fn test_admin_can_set_fee_bps() { let admin = Address::generate(&env); let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); + client.pause(&admin); + client.set_fee_bps(&admin, &100u32); // Should panic +} + +#[test] +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_set_treasury() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let admin = Address::generate(&env); + let treasury = Address::generate(&env); ac_client.grant_role(&admin, &ROLE_ADMIN); client.init(&ac_id, &treasury, &0u32); - client.set_fee_bps(&admin, &500u32); // 5% — should not panic + client.pause(&admin); + client.set_treasury(&admin, &Address::generate(&env)); // Should panic } #[test] -fn test_admin_can_set_treasury() { +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_create_pool() { let env = Env::default(); env.mock_all_auths(); @@ -249,38 +330,145 @@ fn test_admin_can_set_treasury() { let admin = Address::generate(&env); let treasury = Address::generate(&env); - let new_treasury = Address::generate(&env); + let token = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); + + client.pause(&admin); + client.create_pool(&100u64, &token); // Should panic +} +#[test] +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_place_prediction() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let admin = Address::generate(&env); + let user = Address::generate(&env); + let treasury = Address::generate(&env); ac_client.grant_role(&admin, &ROLE_ADMIN); client.init(&ac_id, &treasury, &0u32); - client.set_treasury(&admin, &new_treasury); // Should not panic + client.pause(&admin); + client.place_prediction(&user, &0u64, &10, &1); // Should panic } #[test] -fn test_multiple_pools_independent() { +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_resolve_pool() { let env = Env::default(); env.mock_all_auths(); - let (_, client, token_address, token, token_admin_client, _, operator) = setup(&env); + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); - let user1 = Address::generate(&env); - let user2 = Address::generate(&env); - token_admin_client.mint(&user1, &1000); - token_admin_client.mint(&user2, &1000); + let admin = Address::generate(&env); + let operator = Address::generate(&env); + let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + ac_client.grant_role(&operator, &ROLE_OPERATOR); + client.init(&ac_id, &treasury, &0u32); - let pool_a = client.create_pool(&100u64, &token_address); - let pool_b = client.create_pool(&200u64, &token_address); + client.pause(&admin); + client.resolve_pool(&operator, &0u64, &1u32); // Should panic +} - client.place_prediction(&user1, &pool_a, &100, &1); - client.place_prediction(&user2, &pool_b, &100, &1); +#[test] +#[should_panic(expected = "Contract is paused")] +fn test_paused_blocks_claim_winnings() { + let env = Env::default(); + env.mock_all_auths(); - client.resolve_pool(&operator, &pool_a, &1u32); - client.resolve_pool(&operator, &pool_b, &2u32); // user2 loses + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); - let w1 = client.claim_winnings(&user1, &pool_a); - assert_eq!(w1, 100); // only winner in pool_a, gets back their own stake + let admin = Address::generate(&env); + let user = Address::generate(&env); + let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); - let w2 = client.claim_winnings(&user2, &pool_b); - assert_eq!(w2, 0); // lost in pool_b + client.pause(&admin); + client.claim_winnings(&user, &0u64); // Should panic +} + +#[test] +fn test_unpause_restores_functionality() { + let env = Env::default(); + env.mock_all_auths(); + + let ac_id = env.register(dummy_access_control::DummyAccessControl, ()); + let ac_client = dummy_access_control::DummyAccessControlClient::new(&env, &ac_id); + let contract_id = env.register(PredifiContract, ()); + let client = PredifiContractClient::new(&env, &contract_id); + + let token_admin = Address::generate(&env); + let token_contract = env.register_stellar_asset_contract(token_admin.clone()); + let token_admin_client = token::StellarAssetClient::new(&env, &token_contract); + + let admin = Address::generate(&env); + let user = Address::generate(&env); + let treasury = Address::generate(&env); + ac_client.grant_role(&admin, &ROLE_ADMIN); + client.init(&ac_id, &treasury, &0u32); + token_admin_client.mint(&user, &1000); + + client.pause(&admin); + client.unpause(&admin); + + // After unpause these should work fine + let pool_id = client.create_pool(&100u64, &token_contract); + client.place_prediction(&user, &pool_id, &10, &1); +} + +// ── Pagination tests ────────────────────────────────────────────────────────── + +#[test] +fn test_get_user_predictions() { + let env = Env::default(); + env.mock_all_auths(); + + let (_, client, token_address, _, token_admin_client, _, _) = setup(&env); + + let user = Address::generate(&env); + token_admin_client.mint(&user, &1000); + + let pool0 = client.create_pool(&100u64, &token_address); + let pool1 = client.create_pool(&200u64, &token_address); + let pool2 = client.create_pool(&300u64, &token_address); + + client.place_prediction(&user, &pool0, &10, &1); + client.place_prediction(&user, &pool1, &20, &2); + client.place_prediction(&user, &pool2, &30, &1); + + // Offset 0, Limit 2 + let first_two = client.get_user_predictions(&user, &0, &2); + assert_eq!(first_two.len(), 2); + assert_eq!(first_two.get(0).unwrap().pool_id, pool0); + assert_eq!(first_two.get(1).unwrap().pool_id, pool1); + + // Offset 1, Limit 2 + let last_two = client.get_user_predictions(&user, &1, &2); + assert_eq!(last_two.len(), 2); + assert_eq!(last_two.get(0).unwrap().pool_id, pool1); + assert_eq!(last_two.get(1).unwrap().pool_id, pool2); + + // Offset 2, Limit 1 + let last_one = client.get_user_predictions(&user, &2, &1); + assert_eq!(last_one.len(), 1); + assert_eq!(last_one.get(0).unwrap().pool_id, pool2); + + // Out of bounds + let empty = client.get_user_predictions(&user, &3, &1); + assert_eq!(empty.len(), 0); } diff --git a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json index 51e3380b..e8ced886 100644 --- a/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json +++ b/contract/contracts/predifi-contract/test_snapshots/test/test_claim_winnings.1.json @@ -1,6 +1,6 @@ { "generators": { - "address": 9, + "address": 8, "nonce": 0, "mux_id": 0 }, @@ -28,7 +28,6 @@ ], [], [], - [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", @@ -39,7 +38,7 @@ "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "i128": "1000" @@ -61,7 +60,7 @@ "function_name": "mint", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "i128": "1000" @@ -76,7 +75,7 @@ [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", { "function": { "contract_fn": { @@ -84,7 +83,7 @@ "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u64": "0" @@ -106,7 +105,7 @@ "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" @@ -125,7 +124,7 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", { "function": { "contract_fn": { @@ -133,7 +132,7 @@ "function_name": "place_prediction", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "u64": "0" @@ -155,7 +154,7 @@ "function_name": "transfer", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" @@ -200,7 +199,7 @@ ], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", { "function": { "contract_fn": { @@ -208,7 +207,7 @@ "function_name": "claim_winnings", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u64": "0" @@ -223,7 +222,7 @@ [], [ [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", { "function": { "contract_fn": { @@ -231,7 +230,7 @@ "function_name": "claim_winnings", "args": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "u64": "0" @@ -434,7 +433,7 @@ "symbol": "HasClaimed" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u64": "0" @@ -452,7 +451,7 @@ "symbol": "HasClaimed" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "u64": "0" @@ -574,7 +573,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u64": "0" @@ -609,7 +608,7 @@ "symbol": "Prediction" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "u64": "0" @@ -644,7 +643,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } ] }, @@ -659,7 +658,7 @@ "symbol": "UserPredictionCount" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } ] }, @@ -674,7 +673,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" }, { "u32": 0 @@ -692,7 +691,7 @@ "symbol": "UserPredictionIndex" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" }, { "u32": 0 @@ -816,38 +815,6 @@ { "contract_data": { "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", - "key": "ledger_key_contract_instance", - "durability": "persistent" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_data": { - "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", - "key": "ledger_key_contract_instance", - "durability": "persistent", - "val": { - "contract_instance": { - "executable": { - "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - }, - "storage": null - } - } - } - }, - "ext": "v0" - }, - 4095 - ] - ], - [ - { - "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", "key": { "ledger_key_nonce": { "nonce": "4837995959683129791" @@ -862,7 +829,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", "key": { "ledger_key_nonce": { "nonce": "4837995959683129791" @@ -880,7 +847,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", "key": { "ledger_key_nonce": { "nonce": "8370022561469687789" @@ -895,7 +862,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM", "key": { "ledger_key_nonce": { "nonce": "8370022561469687789" @@ -913,7 +880,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", "key": { "ledger_key_nonce": { "nonce": "2032731177588607455" @@ -928,7 +895,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", "key": { "ledger_key_nonce": { "nonce": "2032731177588607455" @@ -946,7 +913,7 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", "key": { "ledger_key_nonce": { "nonce": "6277191135259896685" @@ -961,7 +928,7 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5", "key": { "ledger_key_nonce": { "nonce": "6277191135259896685" @@ -1056,7 +1023,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } ] }, @@ -1076,7 +1043,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } ] }, @@ -1126,7 +1093,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } ] }, @@ -1146,7 +1113,7 @@ "symbol": "Balance" }, { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5" } ] },