diff --git a/contracts/inheritance-contract/src/lib.rs b/contracts/inheritance-contract/src/lib.rs index eb8099ad0..c99f06d2c 100644 --- a/contracts/inheritance-contract/src/lib.rs +++ b/contracts/inheritance-contract/src/lib.rs @@ -1,5 +1,7 @@ #![no_std] -use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env, String, Vec}; +use soroban_sdk::{ + contract, contracterror, contractimpl, contracttype, symbol_short, Address, Env, String, Vec, +}; const MAX_BENEFICIARIES: u32 = 100; const PLAN_TTL_THRESHOLD: u32 = 500; @@ -147,10 +149,13 @@ impl InheritanceContract { } let mut plan: Plan = env.storage().persistent().get(&key).unwrap(); - plan.last_ping = env.ledger().timestamp(); + let current_timestamp = env.ledger().timestamp(); + plan.last_ping = current_timestamp; env.storage().persistent().set(&key, &plan); Self::extend_plan_ttl(&env, &key); + env.events() + .publish((symbol_short!("ping"), owner), current_timestamp); Ok(()) } diff --git a/contracts/inheritance-contract/src/test.rs b/contracts/inheritance-contract/src/test.rs index b441860e2..aa2517e9b 100644 --- a/contracts/inheritance-contract/src/test.rs +++ b/contracts/inheritance-contract/src/test.rs @@ -1,7 +1,7 @@ use super::*; use soroban_sdk::testutils::Address as _; -use soroban_sdk::testutils::Ledger; -use soroban_sdk::{Address, Env, String, Vec}; +use soroban_sdk::testutils::{Events, Ledger}; +use soroban_sdk::{symbol_short, vec, Address, Env, IntoVal, String, Vec}; #[test] fn test_contract_compilation() { @@ -68,6 +68,91 @@ fn test_create_plan_success() { assert_eq!(plan.beneficiaries.get(0).unwrap().allocation_bps, 10000); } +#[test] +fn test_ping_updates_last_ping_and_emits_event() { + let env = Env::default(); + env.mock_all_auths(); + + let contract_id = env.register_contract(None, InheritanceContract); + let client = InheritanceContractClient::new(&env, &contract_id); + + let token_id = env.register_contract(None, mock_token::MockToken); + let token_client = mock_token::MockTokenClient::new(&env, &token_id); + + let owner = Address::generate(&env); + let beneficiary = Beneficiary { + address: Address::generate(&env), + allocation_bps: 10000, + fiat_anchor_info: String::from_str(&env, "NGN_BANK"), + }; + + token_client.mint(&owner, &2000); + + let start = 1_000_000; + env.ledger().set_timestamp(start); + + client.create_plan( + &owner, + &token_id, + &1500, + &Vec::from_array(&env, [beneficiary]), + &3600, + &true, + &500, + &86400, + ); + assert_eq!(client.get_plan(&owner).last_ping, start); + + let ping_timestamp = start + 1234; + env.ledger().set_timestamp(ping_timestamp); + + client.ping(&owner); + + let plan = client.get_plan(&owner); + assert_eq!(plan.last_ping, ping_timestamp); + assert_eq!( + env.events().all(), + vec![ + &env, + ( + contract_id, + (symbol_short!("ping"), owner).into_val(&env), + ping_timestamp.into_val(&env), + ), + ] + ); +} + +#[test] +#[should_panic] +fn test_ping_requires_owner_auth() { + let env = Env::default(); + + let contract_id = env.register_contract(None, InheritanceContract); + let client = InheritanceContractClient::new(&env, &contract_id); + + let owner = Address::generate(&env); + let key = DataKey::Plan(owner.clone()); + let plan = Plan { + owner: owner.clone(), + token: Address::generate(&env), + amount: 1, + beneficiaries: Vec::new(&env), + last_ping: env.ledger().timestamp(), + grace_period: 3600, + earn_yield: false, + yield_rate_bps: 0, + is_active: true, + timelock_duration: 86400, + }; + + env.as_contract(&contract_id, || { + env.storage().persistent().set(&key, &plan); + }); + + client.ping(&owner); +} + #[test] fn test_create_plan_insufficient_balance() { let env = Env::default();