The Pizza Drop contract is designed to allow users to claim APT tokens, with the contract maintaining sufficient funds to cover all claims.
The contract uses a state-tracked balance (state.balance
) to validate if there were sufficient funds for claims. This state-tracked balance is updated when the fund_pizza_drop
function is called, but this tracking could become out of sync with actual APT balance since direct transfers to the contract address bypass this tracking mechanism.
Likelihood:
When owner (or any user or contract) funds the contract via direct APT transfers (which is standard practice in Aptos)
The issue occurs any time funds arrive through means other than fund_pizza_drop
Impact:
Users cannot claim their allocated APT even when contract has sufficient funds
APT becomes locked in contract when tracked balance is lower than actual (unrecoverable without upgrading contracts)
The test below demonstrates how the balance tracking can be bypassed, leading to a state where users cannot claim their allocated APT even when the contract has sufficient funds. The test:
Funds the contract with 50 APT through the proper fund_pizza_drop
function
Directly transfers 450 APT to the contract, bypassing the balance tracking
Shows that while the contract actually holds 500 APT, it only tracks 50 APT
Demonstrates that claims fail despite having 500 APT available, which should be enough to fund at least a single claim.
This scenario could happen in production if the owner, users or other contracts directly transfer APT to the resource account, a common practice in Aptos. The tracked balance would remain out of sync with the actual balance, potentially leading to permanently locked funds.
Remove state balance tracking entirely and use actual APT balance for validation:
This solution:
Uses a single source of truth (actual APT balance)
Allows funding with direct transfers
Prevents claims from failing when funds are available
Simplifies the code by removing unnecessary state tracking
Removes redundant view function get_pizza_pool_balance
since actual balance can be queried using get_actual_apt_balance
Most importantly, this change ensures that APT sent directly to the resource account will not remain permanently locked if the module is published without upgrade capabilities. With the previous implementation, any APT sent directly would be inaccessible since the tracked balance would prevent claims, and without upgrade capabilities there would be no way to fix this state.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.