Skip to content

Commit 3969bae

Browse files
authored
Merge pull request #205 from Adeyemi-cmd/add_events_for_all_state
feat: Add events for all state-changing user/admin actions
2 parents 4190789 + 44f0439 commit 3969bae

4 files changed

Lines changed: 1092 additions & 4 deletions

File tree

contracts/vault/src/event_tests.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#![cfg(test)]
2+
3+
use super::*;
4+
use soroban_sdk::testutils::Address as _;
5+
use soroban_sdk::{token, Address, Env, symbol_short};
6+
7+
fn create_token_contract<'a>(env: &Env, admin: &Address) -> token::Client<'a> {
8+
let token_address = env.register_stellar_asset_contract_v2(admin.clone()).address();
9+
token::Client::new(env, &token_address)
10+
}
11+
12+
fn find_event_by_name(env: &Env, event_name: &str) -> bool {
13+
env.events()
14+
.all()
15+
.iter()
16+
.any(|e| e.topics.get(0) == Some(&symbol_short!(event_name)))
17+
}
18+
19+
#[test]
20+
fn test_deposit_emits_event() {
21+
let env = Env::default();
22+
env.mock_all_auths();
23+
24+
let admin = Address::generate(&env);
25+
let user = Address::generate(&env);
26+
let token_admin = Address::generate(&env);
27+
let usdc = create_token_contract(&env, &token_admin);
28+
let usdc_admin = token::StellarAssetClient::new(&env, &usdc.address);
29+
usdc_admin.mint(&user, &1000);
30+
31+
let vault_id = env.register(YieldVault, ());
32+
let vault = YieldVaultClient::new(&env, &vault_id);
33+
vault.initialize(&admin, &usdc.address);
34+
35+
vault.deposit(&user, &100);
36+
assert!(find_event_by_name(&env, "deposit"));
37+
}
38+
39+
#[test]
40+
fn test_withdraw_emits_event() {
41+
let env = Env::default();
42+
env.mock_all_auths();
43+
44+
let admin = Address::generate(&env);
45+
let user = Address::generate(&env);
46+
let token_admin = Address::generate(&env);
47+
let usdc = create_token_contract(&env, &token_admin);
48+
let usdc_admin = token::StellarAssetClient::new(&env, &usdc.address);
49+
usdc_admin.mint(&user, &200);
50+
51+
let vault_id = env.register(YieldVault, ());
52+
let vault = YieldVaultClient::new(&env, &vault_id);
53+
vault.initialize(&admin, &usdc.address);
54+
55+
vault.deposit(&user, &100);
56+
vault.withdraw(&user, &50);
57+
58+
assert!(find_event_by_name(&env, "withdraw"));
59+
}
60+
61+
#[test]
62+
fn test_set_pause_emits_event() {
63+
let env = Env::default();
64+
env.mock_all_auths();
65+
66+
let admin = Address::generate(&env);
67+
let token_admin = Address::generate(&env);
68+
let usdc = create_token_contract(&env, &token_admin);
69+
70+
let vault_id = env.register(YieldVault, ());
71+
let vault = YieldVaultClient::new(&env, &vault_id);
72+
vault.initialize(&admin, &usdc.address);
73+
74+
vault.set_pause(&true);
75+
assert!(find_event_by_name(&env, "vault_paused"));
76+
}
77+
78+
#[test]
79+
fn test_strategy_proposal_created_emits_event() {
80+
let env = Env::default();
81+
env.mock_all_auths();
82+
83+
let admin = Address::generate(&env);
84+
let strategy = Address::generate(&env);
85+
let token_admin = Address::generate(&env);
86+
let usdc = create_token_contract(&env, &token_admin);
87+
88+
let vault_id = env.register(YieldVault, ());
89+
let vault = YieldVaultClient::new(&env, &vault_id);
90+
vault.initialize(&admin, &usdc.address);
91+
92+
vault.create_strategy_proposal(&admin, &strategy);
93+
assert!(find_event_by_name(&env, "strategy_proposal_created"));
94+
}
95+
96+
#[test]
97+
fn test_distribute_yield_emits_event() {
98+
let env = Env::default();
99+
env.mock_all_auths();
100+
101+
let admin = Address::generate(&env);
102+
let token_admin = Address::generate(&env);
103+
let usdc = create_token_contract(&env, &token_admin);
104+
let usdc_admin = token::StellarAssetClient::new(&env, &usdc.address);
105+
usdc_admin.mint(&admin, &500);
106+
107+
let vault_id = env.register(YieldVault, ());
108+
let vault = YieldVaultClient::new(&env, &vault_id);
109+
vault.initialize(&admin, &usdc.address);
110+
111+
vault.distribute_yield(&100);
112+
assert!(find_event_by_name(&env, "yield_distributed"));
113+
}

contracts/vault/src/lib.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![no_std]
22

33
#[cfg(test)]
4-
mod test;
4+
mod event_tests;
55
#[cfg(test)]
66
mod fuzz_math;
77
pub mod strategy;
@@ -126,6 +126,11 @@ impl YieldVault {
126126
env.storage().instance().set(&DataKey::DaoThreshold, &1i128);
127127
env.storage().instance().set(&DataKey::ProposalNonce, &0u32);
128128

129+
env.events().publish(
130+
(symbol_short!("vault_initialized"), admin.clone()),
131+
(token,),
132+
);
133+
129134
Ok(())
130135
}
131136

@@ -134,6 +139,10 @@ impl YieldVault {
134139
let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
135140
admin.require_auth();
136141
env.storage().instance().set(&DataKey::Strategy, &strategy);
142+
env.events().publish(
143+
(symbol_short!("strategy_set"), admin),
144+
(strategy,),
145+
);
137146
}
138147

139148
/// Read the active strategy address.
@@ -148,6 +157,10 @@ impl YieldVault {
148157
let mut state = Self::get_state(&env);
149158
state.is_paused = paused;
150159
env.storage().instance().set(&DataKey::State, &state);
160+
env.events().publish(
161+
(symbol_short!("vault_paused"), admin),
162+
(paused,),
163+
);
151164
}
152165

153166
pub fn is_paused(env: Env) -> bool {
@@ -214,6 +227,10 @@ impl YieldVault {
214227
env.storage()
215228
.instance()
216229
.set(&DataKey::KoreanDebtStrategy, &strategy);
230+
env.events().publish(
231+
(symbol_short!("korean_strategy_configured"), admin),
232+
(strategy,),
233+
);
217234
}
218235

219236
pub fn accrue_korean_debt_yield(env: Env) -> i128 {
@@ -235,6 +252,10 @@ impl YieldVault {
235252
let mut state = Self::get_state(&env);
236253
state.total_assets += harvested;
237254
env.storage().instance().set(&DataKey::State, &state);
255+
env.events().publish(
256+
(symbol_short!("korean_yield_accrued"), admin),
257+
(harvested, state.total_assets),
258+
);
238259

239260
harvested
240261
}
@@ -248,6 +269,10 @@ impl YieldVault {
248269
env.storage()
249270
.instance()
250271
.set(&DataKey::DaoThreshold, &threshold);
272+
env.events().publish(
273+
(symbol_short!("dao_threshold_set"), admin),
274+
(threshold,),
275+
);
251276
}
252277

253278
pub fn create_strategy_proposal(env: Env, proposer: Address, strategy: Address) -> u32 {
@@ -271,6 +296,10 @@ impl YieldVault {
271296
env.storage()
272297
.instance()
273298
.set(&DataKey::Proposal(next_nonce), &proposal);
299+
env.events().publish(
300+
(symbol_short!("strategy_proposal_created"), proposer),
301+
(next_nonce, strategy),
302+
);
274303
next_nonce
275304
}
276305

@@ -313,7 +342,11 @@ impl YieldVault {
313342
.set(&DataKey::Proposal(proposal_id), &proposal);
314343
env.storage()
315344
.instance()
316-
.set(&DataKey::Vote(proposal_id, voter), &true);
345+
.set(&DataKey::Vote(proposal_id, voter.clone()), &true);
346+
env.events().publish(
347+
(symbol_short!("proposal_voted"), voter),
348+
(proposal_id, support, weight),
349+
);
317350
}
318351

319352
pub fn execute_strategy_proposal(env: Env, proposal_id: u32) {
@@ -345,6 +378,10 @@ impl YieldVault {
345378
env.storage()
346379
.instance()
347380
.set(&DataKey::Proposal(proposal_id), &proposal);
381+
env.events().publish(
382+
(symbol_short!("proposal_executed"), env.storage().instance().get(&DataKey::Admin).unwrap()),
383+
(proposal_id, proposal.strategy),
384+
);
348385
}
349386

350387
/// Adds a new RWA shipment to the tracking system.
@@ -380,6 +417,10 @@ impl YieldVault {
380417
env.storage()
381418
.instance()
382419
.set(&DataKey::ShipmentStatusOf(shipment_id), &status);
420+
env.events().publish(
421+
(symbol_short!("shipment_added"), admin),
422+
(shipment_id, status),
423+
);
383424
}
384425

385426
pub fn update_shipment_status(env: Env, shipment_id: u64, new_status: ShipmentStatus) {
@@ -395,7 +436,7 @@ impl YieldVault {
395436
return;
396437
}
397438

398-
let old_key = DataKey::ShipmentByStatus(old_status);
439+
let old_key = DataKey::ShipmentByStatus(old_status.clone());
399440
let new_key = DataKey::ShipmentByStatus(new_status.clone());
400441

401442
let old_ids = env
@@ -417,6 +458,10 @@ impl YieldVault {
417458
env.storage()
418459
.instance()
419460
.set(&DataKey::ShipmentStatusOf(shipment_id), &new_status);
461+
env.events().publish(
462+
(symbol_short!("shipment_status_updated"), admin),
463+
(shipment_id, old_status, new_status),
464+
);
420465
}
421466

422467
/// Returns a paginated list of shipment IDs filtered by status.
@@ -645,6 +690,10 @@ impl YieldVault {
645690
&DataKey::ShareBalance(user.clone()),
646691
&Self::checked_add(user_shares, shares_to_mint)?,
647692
);
693+
env.events().publish(
694+
(symbol_short!("deposit"), user.clone()),
695+
(amount, shares_to_mint),
696+
);
648697

649698
Ok(shares_to_mint)
650699
}
@@ -741,12 +790,19 @@ impl YieldVault {
741790

742791
// Update idle assets
743792
env.storage().instance().set(&DataKey::TotalAssets, &(idle_ta - amount));
793+
env.events().publish(
794+
(symbol_short!("strategy_invested"), admin),
795+
(strategy_addr, amount),
796+
);
744797
Ok(())
745798
}
746799

747800
/// Recall funds from the strategy.
748801
pub fn divest(env: Env, amount: i128) {
749802
// Can be called by admin or internally by withdraw
803+
if amount <= 0 {
804+
return;
805+
}
750806
let strategy_addr = Self::strategy(env.clone()).expect("no strategy set");
751807
let strategy_client = StrategyClient::new(&env, &strategy_addr);
752808

@@ -755,6 +811,10 @@ impl YieldVault {
755811
// The strategy contract should have transferred funds back to the vault
756812
let idle_ta = env.storage().instance().get::<_, i128>(&DataKey::TotalAssets).unwrap_or(0);
757813
env.storage().instance().set(&DataKey::TotalAssets, &(idle_ta + amount));
814+
env.events().publish(
815+
(symbol_short!("strategy_divested"),),
816+
(strategy_addr, amount),
817+
);
758818
}
759819

760820
/// Admin function to distribute realized yield into the vault.
@@ -787,7 +847,7 @@ impl YieldVault {
787847
env.storage().instance().set(&DataKey::State, &state);
788848

789849
env.events().publish(
790-
(symbol_short!("yielddist"), admin),
850+
(symbol_short!("yield_distributed"), admin),
791851
(amount, state.total_assets, state.total_shares),
792852
);
793853
}
@@ -808,6 +868,11 @@ impl YieldVault {
808868
.instance()
809869
.set(&DataKey::TotalAssets, &Self::checked_add(ta, amount)?);
810870

871+
env.events().publish(
872+
(symbol_short!("yield_reported"), strategy),
873+
(amount,),
874+
);
875+
811876
Ok(())
812877
}
813878
}

rustup-init-windows.exe

12.2 MB
Binary file not shown.

0 commit comments

Comments
 (0)