Root + Impact
Description
Financial operations in smart contracts should emit events to provide transparency and enable off-chain monitoring of fund movements
The fund_pizzas()
and withdraw_funds()
functions modify the contract's financial state without emitting events
public entry fun fund_pizzas(account: &signer, amount: u64) acquires PizzaShop {
let shop = borrow_global_mut<PizzaShop>(@pizza_drop);
@> coin::transfer<AptosCoin>(account, @pizza_drop, amount);
@> shop.balance = shop.balance + amount;
}
public entry fun withdraw_funds(account: &signer, amount: u64) acquires PizzaShop {
let shop = borrow_global_mut<PizzaShop>(@pizza_drop);
@> coin::transfer<AptosCoin>(&resource_signer, signer::address_of(account), amount);
@> shop.balance = shop.balance - amount;
}
Risk
Likelihood:
Impact:
Proof of Concept
public fun demonstrate_silent_operations(funder: &signer, owner: &signer) {
fund_pizzas(funder, 1000);
withdraw_funds(owner, 500);
// External observers cannot detect these state changes
// without directly querying contract state repeatedly
}
The absence of events makes financial operations opaque. External monitoring tools cannot detect funding changes, making it impossible to track the contract's financial health or audit fund movements without expensive state queries.
Recommended Mitigation
+ struct FundingEvent has drop, store {
+ funder: address,
+ amount: u64,
+ new_balance: u64
+ }
+
+ struct WithdrawalEvent has drop, store {
+ recipient: address,
+ amount: u64,
+ new_balance: u64
+ }
public entry fun fund_pizzas(account: &signer, amount: u64) acquires PizzaShop {
let shop = borrow_global_mut<PizzaShop>(@pizza_drop);
coin::transfer<AptosCoin>(account, @pizza_drop, amount);
shop.balance = shop.balance + amount;
+ event::emit(FundingEvent {
+ funder: signer::address_of(account),
+ amount,
+ new_balance: shop.balance
+ });
}
public entry fun withdraw_funds(account: &signer, amount: u64) acquires PizzaShop {
let shop = borrow_global_mut<PizzaShop>(@pizza_drop);
coin::transfer<AptosCoin>(&resource_signer, signer::address_of(account), amount);
shop.balance = shop.balance - amount;
+ event::emit(WithdrawalEvent {
+ recipient: signer::address_of(account),
+ amount,
+ new_balance: shop.balance
+ });
}
Adding event structures with drop
and store
abilities enables proper event emission. The events include essential information: actor addresses, amounts, and resulting balance states. This provides transparency for off-chain monitoring and creates an audit trail for all financial operations.