Harvest Increases Balance
Make sure that the balance increases after a harvest
Use Case
In DeFi yield farming protocols, users can deposit assets into a pool and earn rewards. The process of claiming the compounded rewards is called “harvesting”. This assertion ensures that harvesting operations maintain protocol integrity by:
- Preventing harvests that decrease vault balances
- Ensuring price per share remains stable or increases
- Detecting potential yield farming exploits
- Maintaining protocol solvency by enforcing proper reward distribution
This is a critical security parameter because:
- Incorrect harvest implementations could lead to loss of user funds
- Price per share manipulation could enable flash loan attacks
- Balance decreases during harvest could indicate protocol insolvency
- Yield farming exploits often target harvest mechanisms
Applicable Protocols
- Yield farming protocols (e.g., Beefy, Yearn, Harvest)
- Liquidity mining programs
- Staking protocols with reward distribution
- Auto-compounding vaults
These protocols need this assertion because:
- Yield farming protocols rely on accurate reward distribution
- Liquidity mining programs must maintain proper reward accounting
- Staking protocols need to ensure rewards are properly distributed
- Auto-compounding vaults must maintain accurate share pricing
Explanation
The assertion implements a multi-layered approach to verify harvest operations:
-
Pre-harvest State Check:
- Uses
forkPreState()
to capture vault balance and price per share - Establishes baseline metrics before harvest
- Uses
-
Post-harvest Validation:
- Uses
forkPostState()
to verify metrics after harvest - Ensures balance hasn’t decreased (can stay the same if harvested recently)
- Confirms price per share hasn’t decreased
- Uses
-
Sequential State Change Validation:
- Uses
getStateChangesUint()
to monitor all balance changes - Verifies each balance change is valid relative to the previous state
- Prevents manipulation through multiple harvest calls
- Ensures no balance decreases occur at any point during the transaction
- Uses
The assertion uses the following cheatcodes:
forkPreState()
: Captures pre-harvest metricsforkPostState()
: Verifies post-harvest metricsgetStateChangesUint()
: Monitors all balance changesregisterCallTrigger()
: Triggers on harvest function calls
This approach ensures that:
- Harvests never decrease vault balances
- Price per share remains stable or increases
- No unauthorized balance modifications occur
- Protocol solvency is maintained
- Multiple harvest calls in the same transaction are handled correctly
For more information about cheatcodes, see the Cheatcodes Documentation.
Code Example
Note: This code example is maintained in the Phylax Assertion Examples Repository. For a full examples with mock protocol code and tests please refer to the repository.
Testing
To test this assertion:
- Deploy a test instance of the yield farming vault
- Set up initial vault state with assets and rewards
- Execute harvest operations with varying conditions:
- Single harvest with rewards
- Multiple harvests in same transaction
- Harvest with no new rewards
- Verify the assertion correctly:
- Allows harvests that maintain or increase balance
- Prevents harvests that decrease balance
- Maintains price per share stability
- Handles multiple harvest calls correctly
Assertion Best Practices
- Combine with other assertions like ERC20 Drain for comprehensive protection
- Use appropriate balance thresholds based on protocol reward rates
- Consider adding maximum balance increase limits to prevent reward manipulation
- Add checks for price per share throughout the callstack (could be a separate assertion for modularity)