fixed tests
This commit is contained in:
parent
352ec623f0
commit
c5f0323df7
6 changed files with 151 additions and 631 deletions
|
|
@ -1,200 +0,0 @@
|
|||
# LiquidityManager Refactoring Analysis
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The original `LiquidityManager.sol` (439 lines) has been successfully refactored into a modular architecture with 4 separate contracts totaling ~600 lines. This improves maintainability, testability, and separation of concerns while preserving all original functionality.
|
||||
|
||||
## Identified Issues in Original Code
|
||||
|
||||
### 1. **Single Responsibility Principle Violations**
|
||||
- **Mathematical utilities** mixed with business logic
|
||||
- **Oracle validation** embedded in main contract
|
||||
- **Position strategy** tightly coupled with implementation details
|
||||
- **Fee collection** intertwined with position management
|
||||
|
||||
### 2. **Testing and Maintenance Challenges**
|
||||
- **116-line `_set()` function** difficult to test individual position logic
|
||||
- **Mathematical functions** cannot be tested in isolation
|
||||
- **Price validation** logic cannot be unit tested separately
|
||||
- **No clear boundaries** between different responsibilities
|
||||
|
||||
### 3. **Code Reusability Issues**
|
||||
- **Price/tick utilities** could benefit other contracts
|
||||
- **Oracle logic** useful for other price-sensitive contracts
|
||||
- **Position strategy** could be adapted for different tokens
|
||||
|
||||
## Refactoring Solution
|
||||
|
||||
### **Modular Architecture Overview**
|
||||
|
||||
```
|
||||
LiquidityManagerV2
|
||||
├── inherits from ThreePositionStrategy (anti-arbitrage logic)
|
||||
│ ├── inherits from UniswapMath (mathematical utilities)
|
||||
│ └── inherits from VWAPTracker (dormant whale protection)
|
||||
└── inherits from PriceOracle (TWAP validation)
|
||||
```
|
||||
|
||||
### **1. UniswapMath.sol (Mathematical Utilities)**
|
||||
```solidity
|
||||
abstract contract UniswapMath {
|
||||
function _tickAtPrice(bool t0isWeth, uint256 tokenAmount, uint256 ethAmount) internal pure returns (int24);
|
||||
function _tickAtPriceRatio(int128 priceRatioX64) internal pure returns (int24);
|
||||
function _priceAtTick(int24 tick) internal pure returns (uint256);
|
||||
function _clampToTickSpacing(int24 tick, int24 spacing) internal pure returns (int24);
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- ✅ **Pure functions** easily unit testable
|
||||
- ✅ **Reusable** across multiple contracts
|
||||
- ✅ **Gas efficient** (no state variables)
|
||||
- ✅ **Clear responsibility** (mathematical operations only)
|
||||
|
||||
### **2. PriceOracle.sol (TWAP Validation)**
|
||||
```solidity
|
||||
abstract contract PriceOracle {
|
||||
function _isPriceStable(int24 currentTick) internal view returns (bool);
|
||||
function _validatePriceMovement(int24 currentTick, int24 centerTick, int24 tickSpacing, bool token0isWeth)
|
||||
internal pure returns (bool isUp, bool isEnough);
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- ✅ **Isolated oracle logic** for independent testing
|
||||
- ✅ **Configurable parameters** (intervals, deviations)
|
||||
- ✅ **Reusable** for other price-sensitive contracts
|
||||
- ✅ **Clear error handling** for oracle failures
|
||||
|
||||
### **3. ThreePositionStrategy.sol (Anti-Arbitrage Strategy)**
|
||||
```solidity
|
||||
abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||
function _setPositions(int24 currentTick, PositionParams memory params) internal;
|
||||
function _setAnchorPosition(...) internal returns (uint256 pulledHarb);
|
||||
function _setDiscoveryPosition(...) internal returns (uint256 discoveryAmount);
|
||||
function _setFloorPosition(...) internal;
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- ✅ **Separated position logic** for individual testing
|
||||
- ✅ **Clear dependencies** (ANCHOR → DISCOVERY → FLOOR)
|
||||
- ✅ **Economic rationale** documented in each function
|
||||
- ✅ **VWAP exclusivity** clearly implemented (only floor position)
|
||||
|
||||
### **4. LiquidityManagerV2.sol (Main Contract)**
|
||||
```solidity
|
||||
contract LiquidityManagerV2 is ThreePositionStrategy, PriceOracle {
|
||||
// Focused on:
|
||||
// - Uniswap V3 integration (callbacks, minting)
|
||||
// - Access control and fee management
|
||||
// - Orchestration of inherited functionality
|
||||
}
|
||||
```
|
||||
|
||||
## Key Improvements
|
||||
|
||||
### **1. Separation of Concerns**
|
||||
| Responsibility | Original Location | New Location |
|
||||
|----------------|------------------|--------------|
|
||||
| Mathematical utilities | Mixed throughout | `UniswapMath.sol` |
|
||||
| Oracle validation | `_isPriceStable()` | `PriceOracle.sol` |
|
||||
| Position strategy | 116-line `_set()` | `ThreePositionStrategy.sol` |
|
||||
| Uniswap integration | Main contract | `LiquidityManagerV2.sol` |
|
||||
|
||||
### **2. Enhanced Testability**
|
||||
- ✅ **Unit test** mathematical functions in isolation
|
||||
- ✅ **Mock** oracle responses for price validation testing
|
||||
- ✅ **Test** individual position strategies (anchor, discovery, floor)
|
||||
- ✅ **Validate** position dependencies separately
|
||||
|
||||
### **3. Improved Maintainability**
|
||||
- ✅ **Clear boundaries** between different concerns
|
||||
- ✅ **Smaller functions** easier to understand and modify
|
||||
- ✅ **Documented dependencies** between position types
|
||||
- ✅ **Reusable components** for future development
|
||||
|
||||
### **4. Preserved Functionality**
|
||||
- ✅ **Identical behavior** to original contract
|
||||
- ✅ **Same gas efficiency** (abstract contracts have no overhead)
|
||||
- ✅ **All events and errors** preserved
|
||||
- ✅ **Complete API compatibility**
|
||||
|
||||
## Testing Strategy for Refactored Version
|
||||
|
||||
### **1. Unit Tests by Component**
|
||||
```solidity
|
||||
// UniswapMathTest.sol - Test mathematical utilities
|
||||
function testTickAtPrice() { /* Test price → tick conversion */ }
|
||||
function testPriceAtTick() { /* Test tick → price conversion */ }
|
||||
function testClampToTickSpacing() { /* Test tick normalization */ }
|
||||
|
||||
// PriceOracleTest.sol - Test oracle validation
|
||||
function testPriceStabilityValidation() { /* Mock oracle responses */ }
|
||||
function testPriceMovementValidation() { /* Test movement detection */ }
|
||||
|
||||
// ThreePositionStrategyTest.sol - Test position logic
|
||||
function testAnchorPositionSetting() { /* Test shallow liquidity */ }
|
||||
function testDiscoveryPositionDependency() { /* Test pulledHarb dependency */ }
|
||||
function testFloorPositionVWAPUsage() { /* Test VWAP exclusivity */ }
|
||||
```
|
||||
|
||||
### **2. Integration Tests**
|
||||
```solidity
|
||||
// LiquidityManagerV2Test.sol - Test full integration
|
||||
function testAntiArbitrageStrategyValidation() { /* Reuse existing test */ }
|
||||
function testRecenteringOrchestration() { /* Test component coordination */ }
|
||||
```
|
||||
|
||||
## Migration Path
|
||||
|
||||
### **Option 1: Gradual Migration**
|
||||
1. Deploy new modular contracts alongside existing ones
|
||||
2. Test extensively with same parameters
|
||||
3. Gradually migrate functionality
|
||||
4. Deprecate original contract
|
||||
|
||||
### **Option 2: Direct Replacement**
|
||||
1. Comprehensive testing of refactored version
|
||||
2. Deploy as upgrade/replacement
|
||||
3. Maintain identical interface for existing integrations
|
||||
|
||||
## Performance Analysis
|
||||
|
||||
### **Gas Usage Comparison**
|
||||
- ✅ **No overhead** from abstract contracts (compiled away)
|
||||
- ✅ **Same function calls** (inheritance is compile-time)
|
||||
- ✅ **Potential savings** from better optimization opportunities
|
||||
- ✅ **Identical storage layout** (same state variables)
|
||||
|
||||
### **Code Size Comparison**
|
||||
| Metric | Original | Refactored | Change |
|
||||
|--------|----------|------------|--------|
|
||||
| Main contract lines | 439 | 267 | -39% |
|
||||
| Total lines | 439 | ~600 | +37% |
|
||||
| Functions per file | 20+ | 5-8 | Better organization |
|
||||
| Testable units | 1 | 4 | +400% |
|
||||
|
||||
## Recommendations
|
||||
|
||||
### **Immediate Actions**
|
||||
1. ✅ **Deploy and test** refactored version
|
||||
2. ✅ **Create comprehensive test suite** for each component
|
||||
3. ✅ **Validate gas usage** against original contract
|
||||
4. ✅ **Document migration strategy**
|
||||
|
||||
### **Future Enhancements**
|
||||
1. **Library conversion**: Convert `UniswapMath` to library for even better reusability
|
||||
2. **Interface extraction**: Create interfaces for position strategies
|
||||
3. **Plugin architecture**: Allow swappable position strategies
|
||||
4. **Enhanced monitoring**: Add more granular events per component
|
||||
|
||||
## Conclusion
|
||||
|
||||
The refactored `LiquidityManagerV2` maintains 100% functional compatibility while providing:
|
||||
- **Better separation of concerns** for maintainability
|
||||
- **Enhanced testability** for quality assurance
|
||||
- **Improved reusability** for future development
|
||||
- **Clearer documentation** of anti-arbitrage strategy
|
||||
|
||||
This modular architecture makes the sophisticated three-position anti-arbitrage strategy more understandable and maintainable while preserving the proven economic protection mechanisms.
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
# Test Refactoring Summary
|
||||
|
||||
## Overview
|
||||
|
||||
Successfully refactored the LiquidityManager test suite to support the new modular architecture while maintaining all existing functionality and adding comprehensive unit tests for individual components.
|
||||
|
||||
## Test Files Created
|
||||
|
||||
### 1. **Unit Tests for Modular Components**
|
||||
|
||||
#### `/test/libraries/UniswapMath.t.sol` ✅
|
||||
- **15 comprehensive tests** for mathematical utilities
|
||||
- **Tick/price conversion functions** tested in isolation
|
||||
- **Boundary conditions** and **edge cases** covered
|
||||
- **Fuzz testing** for robustness validation
|
||||
- **Round-trip conversions** verified
|
||||
|
||||
**Key Tests:**
|
||||
- `testTickAtPriceBasic()` - Basic price to tick conversion
|
||||
- `testPriceAtTickSymmetry()` - Validates mathematical reciprocals
|
||||
- `testClampToTickSpacing()` - Tick alignment and boundary checking
|
||||
- `testFuzzTickAtPrice()` - Comprehensive input validation
|
||||
|
||||
#### `/test/abstracts/PriceOracle.t.sol` ✅
|
||||
- **15+ tests** for TWAP oracle validation
|
||||
- **Mock Uniswap pool** for isolated testing
|
||||
- **Price stability scenarios** with various deviations
|
||||
- **Price movement validation** for different token orderings
|
||||
- **Oracle failure fallback** behavior testing
|
||||
|
||||
**Key Tests:**
|
||||
- `testPriceStableWithinDeviation()` - Oracle validation logic
|
||||
- `testPriceMovementWethToken0Up()` - Token ordering edge cases
|
||||
- `testPriceStabilityOracleFailureFallback()` - Error handling
|
||||
|
||||
#### `/test/abstracts/ThreePositionStrategy.t.sol` ✅
|
||||
- **20+ tests** for position strategy logic
|
||||
- **Position dependencies** (ANCHOR → DISCOVERY → FLOOR) validated
|
||||
- **VWAP exclusivity** for floor position confirmed
|
||||
- **Asymmetric slippage profile** architecture tested
|
||||
- **Mock implementation** for isolated component testing
|
||||
|
||||
**Key Tests:**
|
||||
- `testAnchorPositionSymmetricAroundCurrentTick()` - Shallow liquidity validation
|
||||
- `testDiscoveryPositionDependsOnAnchor()` - Dependency verification
|
||||
- `testFloorPositionUsesVWAP()` - VWAP exclusivity validation
|
||||
- `testSetPositionsAsymmetricProfile()` - Anti-arbitrage architecture
|
||||
|
||||
### 2. **Integration Tests**
|
||||
|
||||
#### `/test/ModularComponentsTest.t.sol` ✅
|
||||
- **Compilation verification** for all modular components
|
||||
- **Basic functionality testing** of integrated architecture
|
||||
- **Proof that refactoring maintains compatibility**
|
||||
|
||||
### 3. **Analysis Scripts Updated**
|
||||
|
||||
#### `/analysis/SimpleAnalysis.s.sol` ✅
|
||||
- **Updated to reference** modular architecture
|
||||
- **Documentation updated** to reflect new components
|
||||
- **Analysis capabilities preserved** for security research
|
||||
|
||||
#### `/analysis/README.md` ✅
|
||||
- **Comprehensive documentation** of analysis suite capabilities
|
||||
- **Updated references** to LiquidityManagerV2 architecture
|
||||
- **Enhanced coverage** of modular component interactions
|
||||
|
||||
## Test Results Validation
|
||||
|
||||
### ✅ **All Core Tests Pass**
|
||||
```bash
|
||||
forge test --match-test testModularArchitectureCompiles
|
||||
forge test --match-test testUniswapMathCompilation
|
||||
forge test --match-test testTickAtPriceBasic
|
||||
forge test --match-test testAntiArbitrageStrategyValidation
|
||||
```
|
||||
|
||||
### ✅ **Modular Architecture Verified**
|
||||
- **Mathematical utilities** work independently
|
||||
- **Price oracle logic** functions in isolation
|
||||
- **Position strategy** maintains economic dependencies
|
||||
- **Anti-arbitrage protection** preserved in original tests
|
||||
|
||||
### ✅ **Compatibility Maintained**
|
||||
- **Existing anti-arbitrage test** still passes (80% slippage protection)
|
||||
- **Original functionality** completely preserved
|
||||
- **Test architecture** supports both original and modular versions
|
||||
|
||||
## Benefits Achieved
|
||||
|
||||
### **1. Enhanced Test Coverage**
|
||||
| Component | Original | Refactored | Improvement |
|
||||
|-----------|----------|------------|-------------|
|
||||
| Mathematical utilities | Embedded | 15 unit tests | Isolated testing |
|
||||
| Oracle logic | Integrated | 15+ unit tests | Mock-based testing |
|
||||
| Position strategy | Monolithic | 20+ unit tests | Component validation |
|
||||
| **Total test granularity** | **Low** | **High** | **+300% coverage** |
|
||||
|
||||
### **2. Improved Debugging**
|
||||
- **Unit test failures** pinpoint exact component issues
|
||||
- **Mock implementations** allow isolated problem diagnosis
|
||||
- **Mathematical errors** can be caught without full integration
|
||||
- **Oracle issues** testable without blockchain interaction
|
||||
|
||||
### **3. Development Velocity**
|
||||
- **Fast unit tests** for individual components (milliseconds)
|
||||
- **Slower integration tests** only when needed
|
||||
- **Component changes** can be validated independently
|
||||
- **Regression testing** more targeted and efficient
|
||||
|
||||
### **4. Documentation Through Tests**
|
||||
- **Component boundaries** clearly defined through test structure
|
||||
- **Dependencies** explicitly tested and documented
|
||||
- **Economic logic** validated at component level
|
||||
- **Anti-arbitrage strategy** broken down into testable parts
|
||||
|
||||
## Test Architecture Design
|
||||
|
||||
### **Inheritance Hierarchy**
|
||||
```
|
||||
LiquidityManagerTest (original)
|
||||
├── Contains full integration tests
|
||||
├── Anti-arbitrage validation test ✅
|
||||
└── Supports both original and modular contracts
|
||||
|
||||
ModularComponentsTest
|
||||
├── Quick validation of architecture
|
||||
└── Compilation and basic functionality tests
|
||||
|
||||
Component-Specific Tests
|
||||
├── UniswapMathTest (mathematical utilities)
|
||||
├── PriceOracleTest (TWAP validation)
|
||||
└── ThreePositionStrategyTest (position logic)
|
||||
```
|
||||
|
||||
### **Test Separation Strategy**
|
||||
- **Unit tests** for individual components (fast, isolated)
|
||||
- **Integration tests** for full system behavior (comprehensive)
|
||||
- **Compatibility tests** ensuring refactoring doesn't break functionality
|
||||
- **Performance tests** validating no gas overhead from modular design
|
||||
|
||||
## Migration Path for Development
|
||||
|
||||
### **Current State**
|
||||
- ✅ **Original LiquidityManager** fully tested and functional
|
||||
- ✅ **Modular LiquidityManagerV2** compiles and basic functions work
|
||||
- ✅ **Unit tests** provide comprehensive component coverage
|
||||
- ✅ **Analysis scripts** updated for new architecture
|
||||
|
||||
### **Next Steps for Full Integration**
|
||||
1. **Complete LiquidityManagerV2 integration tests**
|
||||
- Create comprehensive test suite that exercises full contract
|
||||
- Validate gas usage equivalent to original
|
||||
- Confirm identical behavior across all scenarios
|
||||
|
||||
2. **Production deployment preparation**
|
||||
- Extensive testing on testnets
|
||||
- Security audit of modular architecture
|
||||
- Performance benchmarking vs original contract
|
||||
|
||||
3. **Gradual migration strategy**
|
||||
- Deploy modular version alongside original
|
||||
- Comparative testing in production conditions
|
||||
- Gradual migration of functionality
|
||||
|
||||
## Key Insights from Refactoring
|
||||
|
||||
### **1. Component Boundaries Well-Defined**
|
||||
The refactoring revealed clear separation of concerns:
|
||||
- **Mathematical utilities** are pure functions (no state)
|
||||
- **Oracle logic** depends only on external data
|
||||
- **Position strategy** has clear input/output boundaries
|
||||
- **Main contract** orchestrates components effectively
|
||||
|
||||
### **2. Anti-Arbitrage Strategy More Understandable**
|
||||
Breaking down the complex `_set()` function into component parts:
|
||||
- **ANCHOR position** creates shallow liquidity (high slippage)
|
||||
- **DISCOVERY position** depends on anchor minting
|
||||
- **FLOOR position** uses VWAP for historical memory
|
||||
- **Dependencies** follow economic logic precisely
|
||||
|
||||
### **3. Testing Strategy More Effective**
|
||||
- **Component tests** catch issues early in development
|
||||
- **Integration tests** validate system behavior
|
||||
- **Mock implementations** enable isolated debugging
|
||||
- **Fuzz testing** more targeted and effective
|
||||
|
||||
## Validation of Refactoring Success
|
||||
|
||||
### ✅ **Functional Equivalence**
|
||||
- Original anti-arbitrage test still passes
|
||||
- Mathematical calculations identical
|
||||
- Position creation logic preserved
|
||||
- Event emission maintained
|
||||
|
||||
### ✅ **Architectural Improvement**
|
||||
- Clear component boundaries
|
||||
- Enhanced testability
|
||||
- Better code organization
|
||||
- Maintained performance
|
||||
|
||||
### ✅ **Development Experience**
|
||||
- Faster test execution for components
|
||||
- Clearer error messages and debugging
|
||||
- Better documentation through test structure
|
||||
- Enhanced maintainability
|
||||
|
||||
## Conclusion
|
||||
|
||||
The test refactoring successfully demonstrates that the modular LiquidityManagerV2 architecture:
|
||||
|
||||
1. **✅ Maintains 100% functional compatibility** with the original design
|
||||
2. **✅ Provides significantly enhanced testability** through component isolation
|
||||
3. **✅ Improves code organization** without sacrificing performance
|
||||
4. **✅ Enables better debugging and maintenance** through clear boundaries
|
||||
5. **✅ Preserves the proven anti-arbitrage protection** mechanism
|
||||
|
||||
The comprehensive test suite provides confidence that the modular architecture can be safely deployed as a drop-in replacement for the original LiquidityManager while providing substantial benefits for ongoing development and maintenance.
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
# VWAP Test Gaps Analysis - Post Dormant Whale Fix
|
||||
|
||||
## Executive Summary
|
||||
With the dormant whale protection implementation, comprehensive VWAPTracker test suite, and anti-arbitrage strategy validation, the most critical security gaps have been addressed. Remaining gaps are lower-priority LiquidityManager integration tests.
|
||||
|
||||
## Context: Anti-Arbitrage Strategy
|
||||
**Trade-Recenter-Reverse Attack**: Trader profits by exploiting predictable rebalancing through: large trade → trigger recenter() → reverse trade at new configuration.
|
||||
|
||||
**Protection**: Asymmetric slippage profile where ANCHOR (shallow liquidity, high slippage) forces attackers through expensive slippage twice, while FLOOR/DISCOVERY (deep liquidity) provide edge protection.
|
||||
|
||||
**Key Architectural Principle**: Only FLOOR uses VWAP (historical memory), while ANCHOR/DISCOVERY use current tick (immediate response).
|
||||
|
||||
---
|
||||
|
||||
## VWAPTracker Tests - COMPREHENSIVE ✅
|
||||
|
||||
### Core VWAP Logic ✅
|
||||
- ✅ **Basic VWAP calculation** (`testSinglePriceRecording`, `testMultiplePriceRecording`)
|
||||
- ✅ **Volume recording from fees** (`testSinglePriceRecording` - validates `volume = fee * 100`)
|
||||
- ✅ **Multi-trade accumulation** (`testConcreteMultipleRecordings` - mathematical precision)
|
||||
- ✅ **70% discount + capital inefficiency** (`testAdjustedVWAPCalculation`)
|
||||
- ✅ **Zero volume edge cases** (`testZeroVolumeHandling`, `testInitialState`)
|
||||
|
||||
### Security & Edge Cases ✅
|
||||
- ✅ **Dormant whale protection** (`testDormantWhaleProtection` - core security)
|
||||
- ✅ **Overflow handling** (`testOverflowHandling`, `testOverflowCompressionRatio`)
|
||||
- ✅ **Compression preserves history** (prevents whale manipulation)
|
||||
- ✅ **Extreme values** (`testLargeButSafeValues`, `testMinimalValues`)
|
||||
- ✅ **Fuzz testing** (`testFuzzVWAPCalculation` - random inputs)
|
||||
|
||||
### Capital Inefficiency ✅
|
||||
- ✅ **Zero capital inefficiency** (`testAdjustedVWAPWithZeroCapitalInefficiency`)
|
||||
- ✅ **Max capital inefficiency** (`testAdjustedVWAPWithMaxCapitalInefficiency`)
|
||||
- ✅ **Variable impact testing** (`testAdjustedVWAPCalculation`)
|
||||
|
||||
**Result**: VWAPTracker has comprehensive test coverage. No gaps remain.
|
||||
|
||||
---
|
||||
|
||||
## LiquidityManager Integration Tests
|
||||
|
||||
### Priority: HIGH
|
||||
|
||||
#### 1. Anti-Arbitrage Strategy Validation ✅
|
||||
**Status**: COMPLETED
|
||||
**Goal**: Prove asymmetric slippage profile protects against trade-recenter-reverse attacks
|
||||
**Details**: Verified ANCHOR (shallow) vs FLOOR/DISCOVERY (deep) liquidity creates expensive round-trip slippage
|
||||
**Test Location**: `test/LiquidityManager.t.sol::testAntiArbitrageStrategyValidation()`
|
||||
**Results**: 80% slippage loss, 17% anchor ratio, validates protection mechanism
|
||||
**Priority Justification**: Core protection mechanism against sophisticated arbitrage
|
||||
|
||||
#### 2. Position Dependency Order Test
|
||||
**Status**: MISSING
|
||||
**Goal**: Verify _set() function order: ANCHOR → DISCOVERY → FLOOR with correct dependencies
|
||||
**Details**: Test that discovery amount depends on anchor's pulledHarb, floor depends on final outstanding supply after all minting
|
||||
**Test Location**: Should be in `test/LiquidityManager.t.sol`
|
||||
**Priority Justification**: Validates economic logic behind position ordering
|
||||
|
||||
#### 3. Floor Position VWAP Exclusivity Test
|
||||
**Status**: MISSING
|
||||
**Goal**: Prove only floor position uses VWAP, anchor/discovery use current tick
|
||||
**Details**: Critical architectural verification - ensure VWAP only affects floor positioning for historical memory
|
||||
**Test Location**: Should be in `test/LiquidityManager.t.sol`
|
||||
**Priority Justification**: Validates separation of historical (floor) vs immediate (anchor/discovery) price responses
|
||||
|
||||
#### 4. EthScarcity vs EthAbundance Scenarios
|
||||
**Status**: MISSING
|
||||
**Goal**: Test EthScarcity vs EthAbundance event emission and VWAP application logic
|
||||
**Details**: Verify different VWAP usage when ETH reserves < vs > required buyback amount
|
||||
**Test Location**: Should be in `test/LiquidityManager.t.sol`
|
||||
|
||||
### Priority: MEDIUM
|
||||
|
||||
#### 5. Floor Position Discount Verification
|
||||
**Status**: PARTIALLY COVERED
|
||||
**Goal**: Verify floor position pricing uses adjusted VWAP (70% + capital inefficiency)
|
||||
**Details**: Current `testVWAPIntegrationValidation` touches this but needs dedicated precision testing.
|
||||
**Gap**: Need exact discount formula verification in isolation.
|
||||
|
||||
### Priority: LOW
|
||||
|
||||
#### 6. Cross-Position Independence
|
||||
**Status**: MISSING
|
||||
**Goal**: Verify anchor/discovery positions unaffected by VWAP changes
|
||||
**Details**: Ensure VWAP compression/changes don't affect non-floor positions.
|
||||
**Note**: Low priority as architecture makes this unlikely to break.
|
||||
|
||||
## Completed ✅
|
||||
|
||||
### ✅ Anti-Arbitrage Strategy Validation
|
||||
**Status**: Completed
|
||||
**Goal**: Prove asymmetric slippage profile protects against trade-recenter-reverse attacks
|
||||
**File**: `test/LiquidityManager.t.sol::testAntiArbitrageStrategyValidation()`
|
||||
**Results**: 80% round-trip slippage loss, 17% anchor liquidity ratio, validates protection mechanism
|
||||
**What it tests**: Trade-recenter-reverse attack simulation, asymmetric liquidity profile validation, economic attack deterrent
|
||||
|
||||
### ✅ VWAP Integration Validation
|
||||
**Status**: Completed
|
||||
**Goal**: Validate VWAP system stability and cross-component behavior
|
||||
**File**: `test/LiquidityManager.t.sol::testVWAPIntegrationValidation()`
|
||||
**What it tests**: System stability, reasonable value ranges, floor positioning differences, cumulative data accumulation
|
||||
|
||||
---
|
||||
|
||||
## Notes for Implementation
|
||||
|
||||
- Current test file: `/home/ubuntu/dev/harb/onchain/test/LiquidityManager.t.sol`
|
||||
- Next recommended task: **Position Dependency Order Test** (highest remaining priority)
|
||||
- Key insight discovered: Floor positioned at tick -176700 vs current -113852 shows 62k tick difference, confirming VWAP-based positioning
|
||||
- Token ordering: HARB is token0 in test setup (`DEFAULT_TOKEN0_IS_WETH = false`)
|
||||
- **_set() Function Analysis**: Position order ANCHOR → DISCOVERY → FLOOR reflects economic dependencies for anti-arbitrage protection
|
||||
|
||||
## Test Architecture Pattern
|
||||
|
||||
Each test should:
|
||||
1. Use `_setupCustom()` for custom scenarios
|
||||
2. Include proper assertions (not just console.log)
|
||||
3. Test specific functionality, not general integration
|
||||
4. Consider token ordering implications (HARB/WETH vs WETH/HARB)
|
||||
5. Verify economic logic makes sense
|
||||
|
|
@ -31,16 +31,23 @@ import "../test/mocks/MockOptimizer.sol";
|
|||
uint24 constant FEE = uint24(10_000); // 1% fee
|
||||
int24 constant TICK_SPACING = 200;
|
||||
int24 constant ANCHOR_SPACING = 5 * TICK_SPACING;
|
||||
int24 constant EXTREME_PRICE_MARGIN = 12000; // Safety margin from tick boundaries
|
||||
|
||||
// Time constants
|
||||
uint256 constant ORACLE_UPDATE_INTERVAL = 5 hours;
|
||||
|
||||
// Trading constants
|
||||
uint256 constant NORMALIZATION_SELL_PERCENTAGE = 100; // 1%
|
||||
uint256 constant NORMALIZATION_BUY_AMOUNT = 0.01 ether;
|
||||
uint256 constant BALANCE_DIVISOR = 2;
|
||||
uint256 constant MIN_TRADE_AMOUNT = 1 ether;
|
||||
uint256 constant FALLBACK_TRADE_DIVISOR = 10;
|
||||
|
||||
// Test bounds constants
|
||||
uint8 constant MIN_FUZZ_ACTIONS = 5;
|
||||
uint8 constant MAX_FUZZ_ACTIONS = 50;
|
||||
uint8 constant MIN_FUZZ_FREQUENCY = 1;
|
||||
uint8 constant MAX_FUZZ_FREQUENCY = 20;
|
||||
|
||||
// Test setup constants
|
||||
uint256 constant INITIAL_LM_ETH_BALANCE = 10 ether;
|
||||
uint256 constant OVERFLOW_TEST_BALANCE = 201 ether;
|
||||
uint256 constant FUZZ_TEST_BALANCE = 20 ether;
|
||||
uint256 constant VWAP_TEST_BALANCE = 100 ether;
|
||||
|
||||
// Error handling constants
|
||||
bytes32 constant AMPLITUDE_ERROR = keccak256("amplitude not reached.");
|
||||
|
|
@ -154,7 +161,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
harberg.setStakingPool(address(stake));
|
||||
vm.prank(feeDestination);
|
||||
harberg.setLiquidityManager(address(lm));
|
||||
vm.deal(address(lm), 10 ether);
|
||||
vm.deal(address(lm), INITIAL_LM_ETH_BALANCE);
|
||||
}
|
||||
|
||||
/// @notice Intelligent recenter function that handles extreme price conditions
|
||||
|
|
@ -173,15 +180,8 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
|
||||
/// @notice Handles extreme price conditions with normalizing swaps
|
||||
function _handleExtremePrice() internal {
|
||||
(, int24 currentTick,,,,,) = pool.slot0();
|
||||
|
||||
if (_isExtremelyExpensive(currentTick)) {
|
||||
console.log("Detected extremely expensive HARB, performing normalizing swap...");
|
||||
_performNormalizingSwap(currentTick, true);
|
||||
} else if (_isExtremelyCheap(currentTick)) {
|
||||
console.log("Detected extremely cheap HARB, performing normalizing swap...");
|
||||
_performNormalizingSwap(currentTick, false);
|
||||
}
|
||||
// Use the unified extreme price handling from UniswapTestBase
|
||||
handleExtremePrice();
|
||||
}
|
||||
|
||||
/// @notice Attempts the recenter operation with proper error handling
|
||||
|
|
@ -194,19 +194,6 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/// @notice Checks if HARB price is extremely expensive
|
||||
/// @param currentTick The current price tick
|
||||
/// @return True if HARB is extremely expensive
|
||||
function _isExtremelyExpensive(int24 currentTick) internal pure returns (bool) {
|
||||
return currentTick >= TickMath.MAX_TICK - EXTREME_PRICE_MARGIN;
|
||||
}
|
||||
|
||||
/// @notice Checks if HARB price is extremely cheap
|
||||
/// @param currentTick The current price tick
|
||||
/// @return True if HARB is extremely cheap
|
||||
function _isExtremelyCheap(int24 currentTick) internal pure returns (bool) {
|
||||
return currentTick <= TickMath.MIN_TICK + EXTREME_PRICE_MARGIN;
|
||||
}
|
||||
|
||||
/// @notice Validates recenter operation results
|
||||
/// @param isUp Whether the recenter moved positions up or down
|
||||
|
|
@ -248,55 +235,6 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/// @notice Performs a normalizing swap to bring extreme prices back to manageable levels
|
||||
/// @param currentTick The current tick position
|
||||
/// @param isExpensive True if HARB is extremely expensive, false if extremely cheap
|
||||
function _performNormalizingSwap(int24 currentTick, bool isExpensive) internal {
|
||||
console.log("Current tick before normalization:", vm.toString(currentTick));
|
||||
|
||||
if (isExpensive) {
|
||||
// HARB is extremely expensive - we need to bring the price DOWN
|
||||
// This means we need to SELL HARB for ETH (not buy HARB with ETH)
|
||||
|
||||
// Get HARB balance from account (who has been buying) to use for normalization
|
||||
uint256 accountHarbBalance = harberg.balanceOf(account);
|
||||
if (accountHarbBalance > 0) {
|
||||
uint256 harbToSell = accountHarbBalance / NORMALIZATION_SELL_PERCENTAGE; // Sell 1% of account's HARB balance
|
||||
if (harbToSell == 0) harbToSell = 1; // Minimum 1 wei
|
||||
|
||||
vm.prank(account);
|
||||
harberg.transfer(address(this), harbToSell);
|
||||
|
||||
console.log("Performing normalizing swap: selling", vm.toString(harbToSell), "HARB to bring price down");
|
||||
|
||||
// Approve for swap
|
||||
harberg.approve(address(pool), harbToSell);
|
||||
|
||||
// Swap should work - if it doesn't, there's a fundamental problem
|
||||
performSwap(harbToSell, false); // false = selling HARB for ETH
|
||||
} else {
|
||||
console.log("No HARB balance available for normalization");
|
||||
}
|
||||
} else {
|
||||
// HARB is extremely cheap - we need to bring the price UP
|
||||
// This means we need to BUY HARB with ETH (not sell HARB)
|
||||
uint256 ethToBuy = NORMALIZATION_BUY_AMOUNT; // Small amount for price normalization
|
||||
|
||||
// Ensure we have enough ETH
|
||||
if (weth.balanceOf(address(this)) < ethToBuy) {
|
||||
vm.deal(address(this), ethToBuy);
|
||||
weth.deposit{value: ethToBuy}();
|
||||
}
|
||||
|
||||
console.log("Performing normalizing swap: buying HARB with", vm.toString(ethToBuy), "ETH to bring price up");
|
||||
performSwap(ethToBuy, true); // true = buying HARB with ETH
|
||||
}
|
||||
|
||||
// Check the new price
|
||||
(, int24 newTick,,,,,) = pool.slot0();
|
||||
console.log("New tick after normalization:", vm.toString(newTick));
|
||||
console.log("Price change:", vm.toString(newTick - currentTick), "ticks");
|
||||
}
|
||||
|
||||
/// @notice Retrieves liquidity position information for a specific stage
|
||||
/// @param s The liquidity stage (FLOOR, ANCHOR, DISCOVERY)
|
||||
|
|
@ -411,7 +349,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
/// @notice Tests overflow handling in cumulative calculations
|
||||
/// @dev Simulates extreme values that could cause arithmetic overflow
|
||||
function testHandleCumulativeOverflow() public {
|
||||
_setupCustom(false, 201 ether);
|
||||
_setupCustom(false, OVERFLOW_TEST_BALANCE);
|
||||
|
||||
vm.store(address(lm), bytes32(uint256(0)), bytes32(uint256(type(uint256).max - 10)));
|
||||
|
||||
|
|
@ -507,7 +445,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
|
||||
// Test client-side detection and normalization
|
||||
console.log("\n=== PHASE 2: Test client-side normalization ===");
|
||||
if (postBuyTick >= TickMath.MAX_TICK - EXTREME_PRICE_MARGIN) {
|
||||
if (postBuyTick >= TickMath.MAX_TICK - 15000) {
|
||||
console.log("[SUCCESS] Successfully pushed to extreme expensive range");
|
||||
console.log("[SUCCESS] Client-side detection should trigger normalization swap");
|
||||
} else {
|
||||
|
|
@ -740,9 +678,9 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
|
||||
// Diagnose the scenario type
|
||||
console.log("\n=== SCENARIO DIAGNOSIS ===");
|
||||
if (postBuyTick >= TickMath.MAX_TICK - EXTREME_PRICE_MARGIN) {
|
||||
if (postBuyTick >= TickMath.MAX_TICK - 15000) {
|
||||
console.log("[DIAGNOSIS] EXTREME EXPENSIVE HARB - should trigger normalization");
|
||||
} else if (postBuyTick <= TickMath.MIN_TICK + EXTREME_PRICE_MARGIN) {
|
||||
} else if (postBuyTick <= TickMath.MIN_TICK + 15000) {
|
||||
console.log("[DIAGNOSIS] EXTREME CHEAP HARB - potential protocol death");
|
||||
} else {
|
||||
console.log("[DIAGNOSIS] NORMAL RANGE - may still have arithmetic issues");
|
||||
|
|
@ -796,7 +734,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
function _calculateBuyAmount(uint256 baseAmount) internal view returns (uint256) {
|
||||
uint256 wethBalance = weth.balanceOf(account);
|
||||
uint256 amount = baseAmount % (wethBalance / BALANCE_DIVISOR);
|
||||
return amount == 0 ? wethBalance / 10 : amount;
|
||||
return amount == 0 ? wethBalance / FALLBACK_TRADE_DIVISOR : amount;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
|
|
@ -810,11 +748,11 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
/// @param frequency How often to trigger recentering operations
|
||||
/// @param amounts Array of trade amounts to use (bounded automatically)
|
||||
function testFuzzRobustness(uint8 numActions, uint8 frequency, uint8[] calldata amounts) public {
|
||||
vm.assume(numActions > 5 && numActions < 50); // Reasonable bounds for unit testing
|
||||
vm.assume(frequency > 0 && frequency < 20);
|
||||
vm.assume(numActions > MIN_FUZZ_ACTIONS && numActions < MAX_FUZZ_ACTIONS); // Reasonable bounds for unit testing
|
||||
vm.assume(frequency > MIN_FUZZ_FREQUENCY && frequency < MAX_FUZZ_FREQUENCY);
|
||||
vm.assume(amounts.length >= numActions);
|
||||
|
||||
_setupCustom(numActions % 2 == 0 ? true : false, 20 ether);
|
||||
_setupCustom(numActions % 2 == 0 ? true : false, FUZZ_TEST_BALANCE);
|
||||
|
||||
uint256 traderBalanceBefore = weth.balanceOf(account);
|
||||
|
||||
|
|
@ -879,7 +817,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
/// @dev Validates VWAP accumulation, floor positioning, and system stability across trading sequences
|
||||
function testVWAPIntegrationValidation() public {
|
||||
// Setup with known initial conditions
|
||||
_setupCustom(false, 100 ether);
|
||||
_setupCustom(false, VWAP_TEST_BALANCE);
|
||||
|
||||
// Record initial state - should be zero volume
|
||||
assertEq(lm.cumulativeVolumeWeightedPriceX96(), 0, "Initial VWAP should be zero");
|
||||
|
|
@ -1006,7 +944,7 @@ contract LiquidityManagerTest is UniswapTestBase {
|
|||
/// @notice Tests the asymmetric slippage profile that protects against trade-recenter-reverse attacks
|
||||
/// @dev Validates that ANCHOR (shallow) vs FLOOR/DISCOVERY (deep) liquidity creates expensive round-trip slippage
|
||||
function testAntiArbitrageStrategyValidation() public {
|
||||
_setupCustom(false, 100 ether); // HARB is token0, large balance for meaningful slippage testing
|
||||
_setupCustom(false, VWAP_TEST_BALANCE); // HARB is token0, large balance for meaningful slippage testing
|
||||
|
||||
// Phase 1: Record initial state and execute first large trade
|
||||
(, int24 initialTick,,,,,) = pool.slot0();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ library CSVHelper {
|
|||
*/
|
||||
function createPositionsHeader() internal pure returns (string memory) {
|
||||
return
|
||||
"precedingAction, currentTick, floorTickLower, floorTickUpper, floorEth, floorHarb, anchorTickLower, anchorTickUpper, anchorEth, anchorHarb, discoveryTickLower, discoveryTickUpper, discoveryEth, discoveryHarb";
|
||||
"precedingAction, currentTick, floorTickLower, floorTickUpper, floorEth, floorHarb, anchorTickLower, anchorTickUpper, anchorEth, anchorHarb, discoveryTickLower, discoveryTickUpper, discoveryEth, discoveryHarb, token0isWeth";
|
||||
}
|
||||
|
||||
function createTimeSeriesHeader() internal pure returns (string memory) {
|
||||
|
|
|
|||
|
|
@ -43,27 +43,73 @@ abstract contract UniswapTestBase is Test {
|
|||
if (zeroForOne) {
|
||||
// Swapping token0 for token1 - price goes down
|
||||
// sqrtPriceLimitX96 must be less than current price but greater than MIN_SQRT_RATIO
|
||||
limit = TickMath.MIN_SQRT_RATIO + 1;
|
||||
uint160 minAllowedLimit = TickMath.MIN_SQRT_RATIO + 1;
|
||||
if (currentSqrtPrice <= minAllowedLimit + PRICE_LIMIT_BUFFER) {
|
||||
// If we're very close to the min, use the absolute minimum
|
||||
limit = minAllowedLimit;
|
||||
} else {
|
||||
// Use a limit that's reasonably below current price to avoid SPL
|
||||
// Set limit to be halfway between MIN_SQRT_RATIO and current price
|
||||
limit = minAllowedLimit + (currentSqrtPrice - minAllowedLimit) / 2;
|
||||
}
|
||||
} else {
|
||||
// Swapping token1 for token0 - price goes up
|
||||
// sqrtPriceLimitX96 must be greater than current price but less than MAX_SQRT_RATIO
|
||||
// At extreme high prices, we need to be more conservative with the limit
|
||||
uint160 maxAllowedLimit = TickMath.MAX_SQRT_RATIO - 1;
|
||||
if (currentSqrtPrice >= maxAllowedLimit - 1000) {
|
||||
if (currentSqrtPrice >= maxAllowedLimit - PRICE_LIMIT_BUFFER) {
|
||||
// If we're very close to the max, use a more conservative limit
|
||||
limit = currentSqrtPrice + (maxAllowedLimit - currentSqrtPrice) / 2;
|
||||
} else {
|
||||
limit = maxAllowedLimit;
|
||||
// Use a limit that's reasonably above current price to avoid SPL
|
||||
// Set limit to be halfway between current price and MAX_SQRT_RATIO
|
||||
limit = currentSqrtPrice + (maxAllowedLimit - currentSqrtPrice) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
pool.swap(account, zeroForOne, int256(amount), limit, abi.encode(account, int256(amount), isBuy));
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Performs a swap with aggressive price limits for extreme price normalization
|
||||
* @param amount The amount to swap
|
||||
* @param isBuy True if buying HARB, false if selling HARB
|
||||
*/
|
||||
function performSwapWithAggressiveLimits(uint256 amount, bool isBuy) internal {
|
||||
uint160 limit;
|
||||
// Determine the swap direction
|
||||
bool zeroForOne = isBuy ? token0isWeth : !token0isWeth;
|
||||
|
||||
if (isBuy) {
|
||||
vm.prank(account);
|
||||
weth.transfer(address(this), amount);
|
||||
} else {
|
||||
vm.prank(account);
|
||||
harberg.approve(address(this), amount);
|
||||
}
|
||||
|
||||
// Set aggressive price limits that allow price to move to liquidity ranges
|
||||
if (zeroForOne) {
|
||||
// Swapping token0 for token1 - price goes down
|
||||
// Use very aggressive limit close to MIN_SQRT_RATIO
|
||||
limit = TickMath.MIN_SQRT_RATIO + 1;
|
||||
} else {
|
||||
// Swapping token1 for token0 - price goes up
|
||||
// Use very aggressive limit close to MAX_SQRT_RATIO
|
||||
limit = TickMath.MAX_SQRT_RATIO - 1;
|
||||
}
|
||||
|
||||
pool.swap(account, zeroForOne, int256(amount), limit, abi.encode(account, int256(amount), isBuy));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev The Uniswap V3 swap callback.
|
||||
*/
|
||||
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external {
|
||||
// Handle the case where no swap occurred (both deltas are 0)
|
||||
if (amount0Delta == 0 && amount1Delta == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
require(amount0Delta > 0 || amount1Delta > 0);
|
||||
|
||||
(address seller,, bool isBuy) = abi.decode(_data, (address, uint256, bool));
|
||||
|
|
@ -99,4 +145,78 @@ abstract contract UniswapTestBase is Test {
|
|||
weth.transfer(msg.sender, amount1Owed);
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// EXTREME PRICE HANDLING
|
||||
// ========================================
|
||||
|
||||
// Safety margin to prevent tick boundary violations (conservative approach)
|
||||
int24 constant TICK_BOUNDARY_SAFETY_MARGIN = 15000;
|
||||
|
||||
// Price normalization constants
|
||||
uint256 constant NORMALIZATION_HARB_PERCENTAGE = 100; // 1% of HARB balance
|
||||
uint256 constant NORMALIZATION_ETH_AMOUNT = 0.01 ether; // Fixed ETH amount for normalization
|
||||
uint256 constant MAX_NORMALIZATION_ATTEMPTS = 3; // Prevent infinite loops
|
||||
uint256 constant PRICE_LIMIT_BUFFER = 1000; // Buffer from sqrt price limits
|
||||
|
||||
/**
|
||||
* @notice Handles extreme price conditions by executing normalizing trades
|
||||
* @dev This function should be called before any recenter operation to ensure
|
||||
* the price is within safe boundaries for liquidity position creation
|
||||
*/
|
||||
function handleExtremePrice() internal {
|
||||
uint256 attempts = 0;
|
||||
|
||||
while (attempts < MAX_NORMALIZATION_ATTEMPTS) {
|
||||
(, int24 currentTick,,,,,) = pool.slot0();
|
||||
|
||||
if (currentTick >= TickMath.MAX_TICK - TICK_BOUNDARY_SAFETY_MARGIN) {
|
||||
_executeNormalizingTrade(true); // Move price down
|
||||
attempts++;
|
||||
} else if (currentTick <= TickMath.MIN_TICK + TICK_BOUNDARY_SAFETY_MARGIN) {
|
||||
_executeNormalizingTrade(false); // Move price up
|
||||
attempts++;
|
||||
} else {
|
||||
// Price is now safe, exit loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @notice Executes a small trade to move price away from tick boundaries
|
||||
* @param moveDown True to move price down (sell HARB), false to move price up (buy HARB)
|
||||
*/
|
||||
function _executeNormalizingTrade(bool moveDown) internal {
|
||||
if (moveDown) {
|
||||
// Need to move price DOWN (reduce HARB price)
|
||||
// This means: sell HARB for ETH (increase HARB supply in pool)
|
||||
uint256 harbBalance = harberg.balanceOf(account);
|
||||
if (harbBalance > 0) {
|
||||
// Use 1% of account's HARB balance (conservative approach like original)
|
||||
uint256 harbToSell = harbBalance / NORMALIZATION_HARB_PERCENTAGE;
|
||||
if (harbToSell == 0) harbToSell = 1;
|
||||
|
||||
vm.prank(account);
|
||||
harberg.transfer(address(this), harbToSell);
|
||||
harberg.approve(address(pool), harbToSell);
|
||||
|
||||
// Sell HARB for ETH with aggressive price limits for normalization
|
||||
performSwapWithAggressiveLimits(harbToSell, false);
|
||||
}
|
||||
} else {
|
||||
// Need to move price UP (increase HARB price)
|
||||
// This means: buy HARB with ETH (reduce HARB supply in pool)
|
||||
uint256 ethBalance = weth.balanceOf(account);
|
||||
if (ethBalance > 0) {
|
||||
// Use small amount for normalization (like original)
|
||||
uint256 ethToBuy = NORMALIZATION_ETH_AMOUNT;
|
||||
if (ethToBuy > ethBalance) ethToBuy = ethBalance;
|
||||
|
||||
// Buy HARB with ETH with aggressive price limits for normalization
|
||||
performSwapWithAggressiveLimits(ethToBuy, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue