The burn tax rate change validation can be bypassed when setting extreme rate changes that exceed the allowed increment limit, and this breaks the protocol's tax rate adjustment safeguards and could lead to sudden, dramatic tax rate changes that harm user experience.
The issue arises in the validation logic of setBurnTaxRate. While the contract checks that new rates don't exceed MAX_TAX_RATE (1000 basis points), the increment limit check can be bypassed when setting certain rate combinations.
Root Cause:
The validation attempts to calculate the maximum allowed change, but the integer arithmetic creates an unexpected behavior. For example, with:
Current burn tax rate: 500 (5%)
Increment limit: 1000 (10%)
Proposed new rate: 800 (8%)
The contract should reject this 3% jump, but it doesn't. This means users could experience unexpected tax rate changes that exceed the protocol's intended gradual adjustment mechanism.
this creates a ripple effect through these interconnected contracts:
RAACToken.sol: Core tax rate logic
IRAACToken.sol: Interface defining tax rate constraints
RAACGauge.sol: Reward calculations affected by tax rates
veRAACToken.sol: Voting power and boost mechanisms
LendingPool.sol: Collateral value calculations
When examining the RAACToken contract and how tax rates are meant to change gradually through controlled increments. The protocol uses both swap and burn tax rates, with a maximum of 10% (1000 basis points) and incremental limits to prevent sudden changes. However, the current implementation has a flaw in its validation logic.
We expects tax rate changes to stay within defined increment limits, but here's where its twisted in _setTaxRate
The tax system interacts with multiple protocol components. The LendingPool uses tax rates to manage lending risk, while the GaugeController factors them into reward calculations. This interconnected system requires careful balance, which is why the tax rate changes are designed to be gradual and predictable.
The core problem lies in how the protocol validates tax rate changes. When a tax rate update is proposed, the contract calculates the maximum allowed change using percentage multiplication. This seemingly approach has a flaw in its integer arithmetic that becomes apparent when we look at specific scenarios.
Happens in practice. Imagine the current burn tax rate is 5% (500 basis points) and someone attempts to change it to 8% (800 basis points). The protocol's increment limit is set to 10%, which should only allow a maximum change of 50 basis points. However, due to how the validation performs its calculations, this excessive jump succeeds despite violating the protocol's economic design.
This means that rapid tax rate changes become possible, undermining RAAC's carefully designed stability mechanisms. The impact ripples through the entire protocol from the RAACGauge reward calculations to the veRAACToken holder incentives.
A thoughtful tax system is built with:
Dual tax types (swap/burn) for different protocol actions
Maximum rate caps to prevent excessive fees
Incremental limits for stability
However, the integer arithmetic in the validation creates edge cases that bypass these carefully designed controls. This particularly impacts:
LendingPool stability (LendingPool.sol)
Gauge voting incentives (RAACGauge.sol)
veRAACToken holder expectations
Implementing precise bounds checking and safer arithmetic operations, we can maintain the protocol's economic stability while preserving its flexible tax adjustment capability. This approach aligns with RAAC's core mission of bringing real estate on-chain in a stable and efficient manner, ensuring that tax rate changes serve their intended purpose of protocol governance without introducing unexpected volatility.
The current code uses percentMul for calculations:
While the proposed fix uses direct multiplication with BASIS_POINTS:
The vulnerability lies in how percentMul handles the calculations. The percentMul function typically implements percentage calculations with specific rounding behavior that can lead to precision issues in edge cases. By using direct multiplication with BASIS_POINTS division, we achieve more predictable and precise results.
This difference becomes significant when dealing with certain tax rate combinations, particularly when:
Current rate is near the MAX_TAX_RATE
Tax rate changes are close to the increment limit
Multiple rate changes occur in sequence
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.