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

Inconsistent Accounting Between state.balance and actual APT Balance

Root + Impact

Description

  • state.balance is manual bookkeeping and can easily drift from the true on-chain balance (coin::balance<AptosCoin>(resource_addr)).


Anyone can transfer APT directly into the resource account, inflating the actual coin balance but not updating state.balance.

// Line number 71 to 102
// In fund_pizza_drop
coin::transfer<AptosCoin>(owner, resource_addr, amount);
state.balance = state.balance + amount;
// In claim_pizza_slice
transfer_from_contract(user_addr, amount);
state.balance = state.balance - amount;

Risk

Likelihood:

  • Any external actor can send coins to the resource account outside the contract.

  • Owner mistakes can also desync accounting.

Impact:

  • Internal state may show insufficient funds, blocking legitimate claims even when APT is available.

  • Or, it may allow over-claims if state.balance is higher than reality.

Proof of Concept

  1. Attacker sends APT directly to the resource account.

  2. get_actual_apt_balance() returns higher than state.balance.

  3. Contract logic misreports balances, leading to inconsistencies.

// Attacker will send APT directly to resource accound and resource account balance will actually shoot up but not updated in the codebase
// get_actual_apt_balance() function will return a different value than the state.balance (since actual balance is different)
// There is a difference in the balance values and hence causes inconsistencies in balance

Recommended Mitigation

Instead of updating the balance using state.balance value and then updating using amount value, we should use the balance of tokens on the Aptos blockchain instead of manually updating the balance everytime and tracking it manually.

- state.balance = state.balance + amount;
- state.balance = state.balance - amount;
+ // Use actual on-chain balance instead of manual tracking
+ let resource_addr = get_resource_address();
+ let balance = coin::balance<AptosCoin>(resource_addr);
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.