[PT1-389] Feature/base fee adjuster normolization#83
[PT1-389] Feature/base fee adjuster normolization#83ifelsedeveloper wants to merge 2 commits intomainfrom
Conversation
- Added token1Decimals parameter to BaseFeeAdjusterArgsBuilder for better normalization of costs in token1. - Updated related functions and tests to accommodate the new parameter, ensuring accurate calculations for tokens with different decimal places. - Introduced a new test case to validate normalization behavior for 6-decimal tokens, addressing previous issues with gas cost calculations.
|
Claude finished @ifelsedeveloper's task —— View job Code Review for PR #83: BaseFeeAdjuster Decimal Normalization FixI've completed my review of this PR that fixes a critical decimal scaling bug in Review Checklist:
SummaryOverall Assessment: ✅ The fix correctly addresses the decimal scaling bug with a well-designed solution. Code Quality & Best PracticesStrengths:
Implementation Review (src/instructions/BaseFeeAdjuster.sol):The fix is mathematically sound: // AFTER: normalizes to token1's native precision
uint256 extraCostInToken1 = (extraGasCost * ethToToken1Price) / (10 ** (36 - token1Decimals));
Test CoverageExcellent Test Coverage:
Test Quality:The new test properly validates:
Potential Issues1. Breaking Change (As documented):
2. Edge Case - Zero Decimals:
3. Parameter Validation:
Performance Considerations✅ Minimal Impact:
Security Assessment✅ No Security Concerns:
Backward Compatibility✅ Verified:
Recommendations
ConclusionThis is a high-quality fix for a critical bug. The implementation is clean, well-tested, and properly documented. The breaking change is unavoidable but handled transparently. I recommend approval after considering the optional validation suggestion. |
alexbabits
left a comment
There was a problem hiding this comment.
Fix is correct, test_BaseFeeAdjusterNormalizationWith6Decimals test passes showing that the issue is fixed. Also wrote a test for 20 decimal token (over 18) and it passes.
However, one thing you may want to consider, is if we trust Maker with token1Decimals input during his order build?
E.g. He lies about this and inputs 6 or 8 or 24 when the actual token 1 decimal is 18.
As far as I can see, during a Taker order that fills this malicious Maker order, the Taker has a thresholdAmount check in TakerTraits.validate(), so that protects from a malicious maker.
If Taker doesn't set thresholdAmount with unlimited slippage, sure he gets screwed now, but that's his own footgun. I think the Taker will always set a reasonable threshold/slippage?
Also Maker's program bytecode is public and it would be possible to see the malicious token1Decimals amount against the real token decimals.
If you think that's worth changing, the fix would be to force IERC20.decimals() call and not trust maker for token1Decimals amount, but I don't think this is needed.
Change Summary
What does this PR change?
Fixes a decimal scaling bug in
BaseFeeAdjuster._baseFeeAdjuster1DwhereextraCostInToken1was computed in 1e18 scale regardless of token1's actual decimals. For non-18-decimal tokens (e.g., USDC with 6 decimals), the gas compensation ratio was inflated by10^(18 - token1Decimals), causingpriceIncreaseto saturate tomaxIncreaseon every swap even with a 1 gwei delta above base — resulting in maker overpaying up to the configured cap on every fill.Related Issue/Ticket:
PT1-389 — BaseFeeAdjuster decimal scaling error (High severity)
Root Cause
Fix
Added
uint8 token1Decimalsparameter (1 byte) toBaseFeeAdjusterArgsBuilder. Normalization divides by10^(36 - token1Decimals)instead of1e18:Files Changed
src/instructions/BaseFeeAdjuster.soltoken1Decimalsto args builder/parser, normalized formulatest/BaseFeeAdjuster.t.sol18, added 6-decimal regression testtest/invariants/BaseFeeAdjusterInvariants.t.sol18test/invariants/BaseFeeAdjusterFeesInvariants.t.sol18.gas-snapshotTesting & Verification
How was this tested?
Test results: 629/629 passed, 0 failed, 0 skipped.
New test —
test_BaseFeeAdjusterNormalizationWith6Decimals:token1Decimals = 6Before the fix, even +1 gwei above base saturated to the 1% cap for 6-decimal tokens.
Risk Assessment
Risk Level:
Risks & Impact
BaseFeeAdjusterArgsBuilder.build()now requires a 5th argument (token1Decimals). Existing bytecode programs using BaseFeeAdjuster will fail to parse (args length 31 → 32 bytes). All orders must be re-created with the new encoding.token1Decimals = 18produces identical behavior to the old formula (10^(36-18) = 10^18).