Beginner FriendlyGameFi
100 EXP
View results
Submission Details
Impact: medium
Likelihood: low
Invalid

M-02: Missing Events for Financial Operations

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;
// No event emission for funding operation
}
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;
// No event emission for withdrawal operation
}

Risk

Likelihood:

  • Every funding and withdrawal operation occurs without event emissions

  • Off-chain monitoring systems cannot track financial state changes

Impact:

  • Poor transparency for users monitoring contract financial health

  • Difficulty in auditing fund movements and detecting financial anomalies

Proof of Concept

// Demonstrate lack of observability
public fun demonstrate_silent_operations(funder: &signer, owner: &signer) {
// These operations succeed but provide no external visibility
fund_pizzas(funder, 1000); // Silent funding - no event
withdraw_funds(owner, 500); // Silent withdrawal - no event
// External observers cannot detect these state changes
// without directly querying contract state repeatedly
// Users cannot track:
// - When funds were added to support pizza giveaways
// - When owner withdraws excess funds
// - Historical funding patterns or withdrawal amounts
}

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.

Updates

Appeal created

bube Lead Judge 10 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.