From bba9781cff1b0a942520cdaa36f7cd819b5c84ac Mon Sep 17 00:00:00 2001 From: Oshioke-Salaki Date: Fri, 20 Feb 2026 22:24:44 +0100 Subject: [PATCH 1/2] feat: emit contract events for access control and predifi contract operations. --- contract/contracts/access-control/src/lib.rs | 121 ++++++++++++++++-- .../contracts/predifi-contract/src/lib.rs | 50 +++++++- 2 files changed, 156 insertions(+), 15 deletions(-) diff --git a/contract/contracts/access-control/src/lib.rs b/contract/contracts/access-control/src/lib.rs index ab68cce..de134ec 100644 --- a/contract/contracts/access-control/src/lib.rs +++ b/contract/contracts/access-control/src/lib.rs @@ -1,15 +1,52 @@ #![no_std] use predifi_errors::PrediFiError; -use soroban_sdk::{contract, contractimpl, contracttype, Address, Env}; +use soroban_sdk::{ + contract, contractevent, contractimpl, contracttype, Address, Env, IntoVal, Symbol, Vec, +}; -#[contracttype] +#[contractevent] #[derive(Clone, Debug, Eq, PartialEq)] -pub enum Role { - Admin = 0, - Operator = 1, - Moderator = 2, - Oracle = 3, - User = 4, +pub struct AdminInitEvent { + pub admin: Address, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RoleAssignedEvent { + pub admin: Address, + pub user: Address, + pub role: Role, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RoleRevokedEvent { + pub admin: Address, + pub user: Address, + pub role: Role, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct RoleTransferredEvent { + pub admin: Address, + pub from: Address, + pub to: Address, + pub role: Role, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AdminTransferredEvent { + pub admin: Address, + pub new_admin: Address, +} + +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AllRolesRevokedEvent { + pub admin: Address, + pub user: Address, } #[contracttype] @@ -68,7 +105,9 @@ impl AccessControl { // Also grant the Admin role to the admin address. env.storage() .persistent() - .set(&DataKey::Role(admin, Role::Admin), &()); + .set(&DataKey::Role(admin.clone(), Role::Admin), &()); + + env.events().publish((), AdminInitEvent { admin }); } /// Returns the current super admin address. @@ -111,7 +150,16 @@ impl AccessControl { env.storage() .persistent() - .set(&DataKey::Role(user, role), &()); + .set(&DataKey::Role(user.clone(), role.clone()), &()); + + env.events().publish( + (), + RoleAssignedEvent { + admin: admin_caller, + user, + role, + }, + ); Ok(()) } @@ -150,7 +198,16 @@ impl AccessControl { env.storage() .persistent() - .remove(&DataKey::Role(user, role)); + .remove(&DataKey::Role(user.clone(), role.clone())); + + env.events().publish( + (), + RoleRevokedEvent { + admin: admin_caller, + user, + role, + }, + ); Ok(()) } @@ -203,10 +260,20 @@ impl AccessControl { env.storage() .persistent() - .remove(&DataKey::Role(from, role.clone())); + .remove(&DataKey::Role(from.clone(), role.clone())); env.storage() .persistent() - .set(&DataKey::Role(to, role), &()); + .set(&DataKey::Role(to.clone(), role.clone()), &()); + + env.events().publish( + (), + RoleTransferredEvent { + admin: admin_caller, + from, + to, + role, + }, + ); Ok(()) } @@ -241,7 +308,15 @@ impl AccessControl { .remove(&DataKey::Role(current_admin, Role::Admin)); env.storage() .persistent() - .set(&DataKey::Role(new_admin, Role::Admin), &()); + .set(&DataKey::Role(new_admin.clone(), Role::Admin), &()); + + env.events().publish( + (), + AdminTransferredEvent { + admin: admin_caller, + new_admin, + }, + ); Ok(()) } @@ -299,6 +374,14 @@ impl AccessControl { } } + env.events().publish( + (), + AllRolesRevokedEvent { + admin: admin_caller, + user, + }, + ); + Ok(()) } @@ -324,4 +407,14 @@ impl AccessControl { } } +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Role { + Admin = 0, + Operator = 1, + Moderator = 2, + Oracle = 3, + User = 4, +} + mod test; diff --git a/contract/contracts/predifi-contract/src/lib.rs b/contract/contracts/predifi-contract/src/lib.rs index 09826a3..4ca03d8 100644 --- a/contract/contracts/predifi-contract/src/lib.rs +++ b/contract/contracts/predifi-contract/src/lib.rs @@ -1,7 +1,8 @@ #![no_std] use soroban_sdk::{ - contract, contracterror, contractimpl, contracttype, token, Address, Env, IntoVal, Symbol, Vec, + contract, contracterror, contractevent, contractimpl, contracttype, token, Address, Env, + IntoVal, Symbol, Vec, }; const DAY_IN_LEDGERS: u32 = 17280; @@ -66,6 +67,20 @@ pub struct Prediction { pub outcome: u32, } +#[contractevent] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum PredifiEvent { + Init(Address, Address, u32), + Pause(Address), + Unpause(Address), + FeeUpdate(Address, u32), + TreasuryUpdate(Address, Address), + PoolCreated(u64, u64, Address), + PoolResolved(u64, Address, u32), + PredictionPlaced(u64, Address, i128, u32), + WinningsClaimed(u64, Address, i128), +} + #[contract] pub struct PredifiContract; @@ -140,6 +155,15 @@ impl PredifiContract { env.storage().instance().set(&DataKey::Config, &config); env.storage().instance().set(&DataKey::PoolIdCounter, &0u64); Self::extend_instance(&env); + + env.storage().instance().set(&DataKey::Config, &config); + env.storage().instance().set(&DataKey::PoolIdCounter, &0u64); + Self::extend_instance(&env); + + env.events().publish( + (), + PredifiEvent::Init(access_control.clone(), treasury.clone(), fee_bps), + ); } } @@ -150,6 +174,8 @@ impl PredifiContract { .unwrap_or_else(|_| panic!("Unauthorized: missing required role")); env.storage().instance().set(&DataKey::Paused, &true); Self::extend_instance(&env); + + env.events().publish((), PredifiEvent::Pause(admin)); } /// Unpause the contract. Only callable by Admin (role 0). @@ -159,6 +185,8 @@ impl PredifiContract { .unwrap_or_else(|_| panic!("Unauthorized: missing required role")); env.storage().instance().set(&DataKey::Paused, &false); Self::extend_instance(&env); + + env.events().publish((), PredifiEvent::Unpause(admin)); } /// Set fee in basis points. Caller must have Admin role (0). @@ -171,6 +199,9 @@ impl PredifiContract { config.fee_bps = fee_bps; env.storage().instance().set(&DataKey::Config, &config); Self::extend_instance(&env); + + env.events() + .publish((), PredifiEvent::FeeUpdate(admin, fee_bps)); Ok(()) } @@ -183,6 +214,9 @@ impl PredifiContract { config.treasury = treasury; env.storage().instance().set(&DataKey::Config, &config); Self::extend_instance(&env); + + env.events() + .publish((), PredifiEvent::TreasuryUpdate(admin, treasury)); Ok(()) } @@ -218,6 +252,9 @@ impl PredifiContract { .set(&DataKey::PoolIdCounter, &(pool_id + 1)); Self::extend_instance(&env); + env.events() + .publish((), PredifiEvent::PoolCreated(pool_id, end_time, token)); + pool_id } @@ -246,6 +283,9 @@ impl PredifiContract { env.storage().persistent().set(&pool_key, &pool); Self::extend_persistent(&env, &pool_key); + + env.events() + .publish((), PredifiEvent::PoolResolved(pool_id, operator, outcome)); Ok(()) } @@ -295,6 +335,11 @@ impl PredifiContract { env.storage().persistent().set(&count_key, &(count + 1)); Self::extend_persistent(&env, &count_key); + + env.events().publish( + (), + PredifiEvent::PredictionPlaced(pool_id, user, amount, outcome), + ); } /// Claim winnings from a resolved pool. Returns the amount paid out (0 for losers). @@ -360,6 +405,9 @@ impl PredifiContract { let token_client = token::Client::new(&env, &pool.token); token_client.transfer(&env.current_contract_address(), &user, &winnings); + env.events() + .publish((), PredifiEvent::WinningsClaimed(pool_id, user, winnings)); + Ok(winnings) } From 5be6f19bdb84f2ecf9c35c0f195fc71b8e4633c2 Mon Sep 17 00:00:00 2001 From: Oshioke-Salaki Date: Fri, 20 Feb 2026 22:51:04 +0100 Subject: [PATCH 2/2] fix: convert all events to structs using #[contractevent] .publish() pattern --- contract/contracts/access-control/src/lib.rs | 212 ++++-------------- .../contracts/predifi-contract/src/lib.rs | 146 ++++++++---- 2 files changed, 154 insertions(+), 204 deletions(-) diff --git a/contract/contracts/access-control/src/lib.rs b/contract/contracts/access-control/src/lib.rs index de134ec..7e42530 100644 --- a/contract/contracts/access-control/src/lib.rs +++ b/contract/contracts/access-control/src/lib.rs @@ -1,16 +1,24 @@ #![no_std] use predifi_errors::PrediFiError; -use soroban_sdk::{ - contract, contractevent, contractimpl, contracttype, Address, Env, IntoVal, Symbol, Vec, -}; +use soroban_sdk::{contract, contractevent, contractimpl, contracttype, Address, Env}; -#[contractevent] +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Role { + Admin = 0, + Operator = 1, + Moderator = 2, + Oracle = 3, + User = 4, +} + +#[contractevent(topics = ["admin_init"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct AdminInitEvent { pub admin: Address, } -#[contractevent] +#[contractevent(topics = ["role_assigned"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoleAssignedEvent { pub admin: Address, @@ -18,7 +26,7 @@ pub struct RoleAssignedEvent { pub role: Role, } -#[contractevent] +#[contractevent(topics = ["role_revoked"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoleRevokedEvent { pub admin: Address, @@ -26,7 +34,7 @@ pub struct RoleRevokedEvent { pub role: Role, } -#[contractevent] +#[contractevent(topics = ["role_transferred"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoleTransferredEvent { pub admin: Address, @@ -35,14 +43,14 @@ pub struct RoleTransferredEvent { pub role: Role, } -#[contractevent] +#[contractevent(topics = ["admin_transferred"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct AdminTransferredEvent { pub admin: Address, pub new_admin: Address, } -#[contractevent] +#[contractevent(topics = ["all_roles_revoked"])] #[derive(Clone, Debug, Eq, PartialEq)] pub struct AllRolesRevokedEvent { pub admin: Address, @@ -52,28 +60,19 @@ pub struct AllRolesRevokedEvent { #[contracttype] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PoolStatus { - /// The pool is open for predictions. Active, - /// The event has occurred and the outcome is determined. Resolved, - /// The pool is closed for new predictions but not yet resolved. Closed, - /// The outcome is being disputed. Disputed, } #[contracttype] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PoolCategory { - /// Sports-related predictions. Sports, - /// Political predictions. Politics, - /// Financial predictions. Finance, - /// Entertainment predictions. Entertainment, - /// Other categories. Other, } @@ -90,33 +89,18 @@ pub struct AccessControl; #[contractimpl] impl AccessControl { - /// Initialize the contract with an initial admin address. - /// - /// # Arguments - /// * `admin` - The address to be appointed as the initial super admin. - /// - /// # Errors - /// * Panics with `"AlreadyInitializedOrConfigNotSet"` if the contract has already been initialized. pub fn init(env: Env, admin: Address) { if env.storage().instance().has(&DataKey::Admin) { soroban_sdk::panic_with_error!(&env, PrediFiError::AlreadyInitializedOrConfigNotSet); } env.storage().instance().set(&DataKey::Admin, &admin); - // Also grant the Admin role to the admin address. env.storage() .persistent() .set(&DataKey::Role(admin.clone(), Role::Admin), &()); - env.events().publish((), AdminInitEvent { admin }); + AdminInitEvent { admin }.publish(&env); } - /// Returns the current super admin address. - /// - /// # Returns - /// The address of the current super admin. - /// - /// # Errors - /// * Panics with `"NotInitialized"` if the contract hasn't been initialized yet. pub fn get_admin(env: Env) -> Address { env.storage() .instance() @@ -124,17 +108,6 @@ impl AccessControl { .expect("NotInitialized") } - /// Assigns a specific role to a user. - /// - /// Only the current super admin can call this function. - /// - /// # Arguments - /// * `admin_caller` - The address of the admin calling the function. - /// * `user` - The address to receive the role. - /// * `role` - The role to be assigned. - /// - /// # Errors - /// * `Unauthorized` - If the caller is not the super admin. pub fn assign_role( env: Env, admin_caller: Address, @@ -152,29 +125,15 @@ impl AccessControl { .persistent() .set(&DataKey::Role(user.clone(), role.clone()), &()); - env.events().publish( - (), - RoleAssignedEvent { - admin: admin_caller, - user, - role, - }, - ); + RoleAssignedEvent { + admin: admin_caller, + user, + role, + } + .publish(&env); Ok(()) } - /// Revokes a specific role from a user. - /// - /// Only the current super admin can call this function. - /// - /// # Arguments - /// * `admin_caller` - The address of the admin calling the function. - /// * `user` - The address from which the role will be revoked. - /// * `role` - The role to be revoked. - /// - /// # Errors - /// * `Unauthorized` - If the caller is not the super admin. - /// * `InsufficientPermissions` - If the user doesn't have the specified role. pub fn revoke_role( env: Env, admin_caller: Address, @@ -200,42 +159,19 @@ impl AccessControl { .persistent() .remove(&DataKey::Role(user.clone(), role.clone())); - env.events().publish( - (), - RoleRevokedEvent { - admin: admin_caller, - user, - role, - }, - ); + RoleRevokedEvent { + admin: admin_caller, + user, + role, + } + .publish(&env); Ok(()) } - /// Checks if a user has a specific role. - /// - /// # Arguments - /// * `user` - The address to check. - /// * `role` - The role to check for. - /// - /// # Returns - /// `true` if the user has the role, `false` otherwise. pub fn has_role(env: Env, user: Address, role: Role) -> bool { env.storage().persistent().has(&DataKey::Role(user, role)) } - /// Transfers a role from one address to another. - /// - /// Only the current super admin can call this function. - /// - /// # Arguments - /// * `admin_caller` - The address of the admin calling the function. - /// * `from` - The address currently holding the role. - /// * `to` - The address to receive the role. - /// * `role` - The role to be transferred. - /// - /// # Errors - /// * `Unauthorized` - If the caller is not the super admin. - /// * `InsufficientPermissions` - If the `from` address doesn't have the specified role. pub fn transfer_role( env: Env, admin_caller: Address, @@ -265,28 +201,16 @@ impl AccessControl { .persistent() .set(&DataKey::Role(to.clone(), role.clone()), &()); - env.events().publish( - (), - RoleTransferredEvent { - admin: admin_caller, - from, - to, - role, - }, - ); + RoleTransferredEvent { + admin: admin_caller, + from, + to, + role, + } + .publish(&env); Ok(()) } - /// Transfers the super admin status to a new address. - /// - /// Only the current super admin can call this function. - /// - /// # Arguments - /// * `admin_caller` - The address of the current admin. - /// * `new_admin` - The address to become the new super admin. - /// - /// # Errors - /// * `Unauthorized` - If the caller is not the current super admin. pub fn transfer_admin( env: Env, admin_caller: Address, @@ -299,10 +223,8 @@ impl AccessControl { return Err(PrediFiError::Unauthorized); } - // Update the admin address. env.storage().instance().set(&DataKey::Admin, &new_admin); - // Transfer the Admin role record. env.storage() .persistent() .remove(&DataKey::Role(current_admin, Role::Admin)); @@ -310,24 +232,15 @@ impl AccessControl { .persistent() .set(&DataKey::Role(new_admin.clone(), Role::Admin), &()); - env.events().publish( - (), - AdminTransferredEvent { - admin: admin_caller, - new_admin, - }, - ); + AdminTransferredEvent { + admin: admin_caller, + new_admin, + } + .publish(&env); Ok(()) } - /// Checks if a user is the current super admin. - /// - /// # Arguments - /// * `user` - The address to check. - /// - /// # Returns - /// `true` if the user is the current super admin, `false` otherwise. pub fn is_admin(env: Env, user: Address) -> bool { let stored: Option
= env.storage().instance().get(&DataKey::Admin); match stored { @@ -336,16 +249,6 @@ impl AccessControl { } } - /// Revokes all roles from a user. - /// - /// Only the current super admin can call this function. - /// - /// # Arguments - /// * `admin_caller` - The address of the admin calling the function. - /// * `user` - The address from which all roles will be revoked. - /// - /// # Errors - /// * `Unauthorized` - If the caller is not the super admin. pub fn revoke_all_roles( env: Env, admin_caller: Address, @@ -358,7 +261,6 @@ impl AccessControl { return Err(PrediFiError::Unauthorized); } - // Revoke all possible roles. for role in [ Role::Admin, Role::Operator, @@ -374,25 +276,15 @@ impl AccessControl { } } - env.events().publish( - (), - AllRolesRevokedEvent { - admin: admin_caller, - user, - }, - ); + AllRolesRevokedEvent { + admin: admin_caller, + user, + } + .publish(&env); Ok(()) } - /// Checks if a user has any of the specified roles. - /// - /// # Arguments - /// * `user` - The address to check. - /// * `roles` - A vector of roles to check. - /// - /// # Returns - /// `true` if the user has at least one of the specified roles, `false` otherwise. pub fn has_any_role(env: Env, user: Address, roles: soroban_sdk::Vec) -> bool { for role in roles.iter() { if env @@ -407,14 +299,4 @@ impl AccessControl { } } -#[contracttype] -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum Role { - Admin = 0, - Operator = 1, - Moderator = 2, - Oracle = 3, - User = 4, -} - mod test; diff --git a/contract/contracts/predifi-contract/src/lib.rs b/contract/contracts/predifi-contract/src/lib.rs index 4ca03d8..ed1b5dc 100644 --- a/contract/contracts/predifi-contract/src/lib.rs +++ b/contract/contracts/predifi-contract/src/lib.rs @@ -67,20 +67,77 @@ pub struct Prediction { pub outcome: u32, } -#[contractevent] +// ── Events ─────────────────────────────────────────────────────────────────── + +#[contractevent(topics = ["init"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InitEvent { + pub access_control: Address, + pub treasury: Address, + pub fee_bps: u32, +} + +#[contractevent(topics = ["pause"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PauseEvent { + pub admin: Address, +} + +#[contractevent(topics = ["unpause"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct UnpauseEvent { + pub admin: Address, +} + +#[contractevent(topics = ["fee_update"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FeeUpdateEvent { + pub admin: Address, + pub fee_bps: u32, +} + +#[contractevent(topics = ["treasury_update"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct TreasuryUpdateEvent { + pub admin: Address, + pub treasury: Address, +} + +#[contractevent(topics = ["pool_created"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PoolCreatedEvent { + pub pool_id: u64, + pub end_time: u64, + pub token: Address, +} + +#[contractevent(topics = ["pool_resolved"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PoolResolvedEvent { + pub pool_id: u64, + pub operator: Address, + pub outcome: u32, +} + +#[contractevent(topics = ["prediction_placed"])] #[derive(Clone, Debug, Eq, PartialEq)] -pub enum PredifiEvent { - Init(Address, Address, u32), - Pause(Address), - Unpause(Address), - FeeUpdate(Address, u32), - TreasuryUpdate(Address, Address), - PoolCreated(u64, u64, Address), - PoolResolved(u64, Address, u32), - PredictionPlaced(u64, Address, i128, u32), - WinningsClaimed(u64, Address, i128), +pub struct PredictionPlacedEvent { + pub pool_id: u64, + pub user: Address, + pub amount: i128, + pub outcome: u32, } +#[contractevent(topics = ["winnings_claimed"])] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct WinningsClaimedEvent { + pub pool_id: u64, + pub user: Address, + pub amount: i128, +} + +// ───────────────────────────────────────────────────────────────────────────── + #[contract] pub struct PredifiContract; @@ -149,21 +206,19 @@ impl PredifiContract { if !env.storage().instance().has(&DataKey::Config) { let config = Config { fee_bps, - treasury, - access_control, + treasury: treasury.clone(), + access_control: access_control.clone(), }; env.storage().instance().set(&DataKey::Config, &config); env.storage().instance().set(&DataKey::PoolIdCounter, &0u64); Self::extend_instance(&env); - env.storage().instance().set(&DataKey::Config, &config); - env.storage().instance().set(&DataKey::PoolIdCounter, &0u64); - Self::extend_instance(&env); - - env.events().publish( - (), - PredifiEvent::Init(access_control.clone(), treasury.clone(), fee_bps), - ); + InitEvent { + access_control, + treasury, + fee_bps, + } + .publish(&env); } } @@ -175,7 +230,7 @@ impl PredifiContract { env.storage().instance().set(&DataKey::Paused, &true); Self::extend_instance(&env); - env.events().publish((), PredifiEvent::Pause(admin)); + PauseEvent { admin }.publish(&env); } /// Unpause the contract. Only callable by Admin (role 0). @@ -186,7 +241,7 @@ impl PredifiContract { env.storage().instance().set(&DataKey::Paused, &false); Self::extend_instance(&env); - env.events().publish((), PredifiEvent::Unpause(admin)); + UnpauseEvent { admin }.publish(&env); } /// Set fee in basis points. Caller must have Admin role (0). @@ -200,8 +255,7 @@ impl PredifiContract { env.storage().instance().set(&DataKey::Config, &config); Self::extend_instance(&env); - env.events() - .publish((), PredifiEvent::FeeUpdate(admin, fee_bps)); + FeeUpdateEvent { admin, fee_bps }.publish(&env); Ok(()) } @@ -211,12 +265,11 @@ impl PredifiContract { admin.require_auth(); Self::require_role(&env, &admin, 0)?; let mut config = Self::get_config(&env); - config.treasury = treasury; + config.treasury = treasury.clone(); env.storage().instance().set(&DataKey::Config, &config); Self::extend_instance(&env); - env.events() - .publish((), PredifiEvent::TreasuryUpdate(admin, treasury)); + TreasuryUpdateEvent { admin, treasury }.publish(&env); Ok(()) } @@ -239,7 +292,7 @@ impl PredifiContract { end_time, resolved: false, outcome: 0, - token, + token: token.clone(), total_stake: 0, }; @@ -252,8 +305,12 @@ impl PredifiContract { .set(&DataKey::PoolIdCounter, &(pool_id + 1)); Self::extend_instance(&env); - env.events() - .publish((), PredifiEvent::PoolCreated(pool_id, end_time, token)); + PoolCreatedEvent { + pool_id, + end_time, + token, + } + .publish(&env); pool_id } @@ -284,8 +341,12 @@ impl PredifiContract { env.storage().persistent().set(&pool_key, &pool); Self::extend_persistent(&env, &pool_key); - env.events() - .publish((), PredifiEvent::PoolResolved(pool_id, operator, outcome)); + PoolResolvedEvent { + pool_id, + operator, + outcome, + } + .publish(&env); Ok(()) } @@ -336,10 +397,13 @@ impl PredifiContract { env.storage().persistent().set(&count_key, &(count + 1)); Self::extend_persistent(&env, &count_key); - env.events().publish( - (), - PredifiEvent::PredictionPlaced(pool_id, user, amount, outcome), - ); + PredictionPlacedEvent { + pool_id, + user, + amount, + outcome, + } + .publish(&env); } /// Claim winnings from a resolved pool. Returns the amount paid out (0 for losers). @@ -405,8 +469,12 @@ impl PredifiContract { let token_client = token::Client::new(&env, &pool.token); token_client.transfer(&env.current_contract_address(), &user, &winnings); - env.events() - .publish((), PredifiEvent::WinningsClaimed(pool_id, user, winnings)); + WinningsClaimedEvent { + pool_id, + user, + amount: winnings, + } + .publish(&env); Ok(winnings) }