-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54d8a6c
commit 4f9919d
Showing
10 changed files
with
509 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.25; | ||
|
||
// Internal utils | ||
import {TickMath} from "test/libraries/TickMath.sol"; | ||
import {INonfungiblePositionManager} from "test/interfaces/INonfungiblePositionManager.sol"; | ||
|
||
// Internal for testing | ||
import {Base_Test_} from "test/Base.sol"; | ||
|
||
abstract contract Actions is Base_Test_ { | ||
//////////////////////////////////////////////////////////////// | ||
/// --- SETUP | ||
//////////////////////////////////////////////////////////////// | ||
function setUp() public virtual override { | ||
super.setUp(); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- MANAGE LIQUDITY | ||
//////////////////////////////////////////////////////////////// | ||
function addLiquidity(uint256 amount0, uint256 amount1) public returns (uint256, uint128) { | ||
deal(address(token0), address(this), amount0); | ||
deal(address(token1), address(this), amount1); | ||
|
||
// Add liquidity | ||
(uint256 tokenId, uint128 liquidity,,) = nftManager.mint( | ||
INonfungiblePositionManager.MintParams({ | ||
token0: address(token0), | ||
token1: address(token1), | ||
tickSpacing: TICK_SPACING, | ||
tickLower: LOWER_TICK, | ||
tickUpper: UPPER_TICK, | ||
amount0Desired: amount0, | ||
amount1Desired: amount1, | ||
amount0Min: 0, | ||
amount1Min: 0, | ||
recipient: address(this), | ||
deadline: block.timestamp + 100, | ||
sqrtPriceX96: 0 | ||
}) | ||
); | ||
|
||
return (tokenId, liquidity); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- MANAGE GAUGE | ||
//////////////////////////////////////////////////////////////// | ||
function stake(uint256 tokenId) public { | ||
gauge.deposit(tokenId); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- MANAGE SWAP | ||
//////////////////////////////////////////////////////////////// | ||
function swap(address tokenIn, uint256 amountIn) public { | ||
deal(tokenIn, address(this), amountIn); | ||
|
||
bool zeroForOne = tokenIn == address(token0); | ||
int256 amountSpecified = zeroForOne ? int256(amountIn) : -int256(amountIn); | ||
uint160 sqrtPriceLimitX96 = zeroForOne ? TickMath.getSqrtRatioAtTick(-100) : TickMath.getSqrtRatioAtTick(100); | ||
|
||
// Swap | ||
pool.swap({ | ||
recipient: address(this), | ||
zeroForOne: zeroForOne, | ||
amountSpecified: amountSpecified, | ||
sqrtPriceLimitX96: sqrtPriceLimitX96, | ||
data: "" | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.25; | ||
|
||
// Foundry | ||
import {Test} from "forge-std/Test.sol"; | ||
|
||
// Solmate | ||
import {ERC20} from "@solmate/tokens/ERC20.sol"; | ||
import {MockERC20} from "@solmate/test/utils/mocks/MockERC20.sol"; | ||
|
||
// Aerodrome | ||
import {IVoter} from "test/interfaces/IVoter.sol"; | ||
import {ICLPool} from "test/interfaces/ICLPool.sol"; | ||
import {ICLGauge} from "test/interfaces/ICLGauge.sol"; | ||
import {ICLPoolFactory} from "test/interfaces/ICLPoolFactory.sol"; | ||
import {INonfungiblePositionManager} from "test/interfaces/INonfungiblePositionManager.sol"; | ||
|
||
// Internal utils | ||
import {Base} from "test/utils/Addresses.sol"; | ||
import {TickMath} from "test/libraries/TickMath.sol"; | ||
|
||
abstract contract Base_Test_ is Test { | ||
//////////////////////////////////////////////////////////////// | ||
/// --- CONSTANTS & IMMUTABLES | ||
//////////////////////////////////////////////////////////////// | ||
int24 public constant LOWER_TICK = 0; | ||
int24 public constant UPPER_TICK = 1; | ||
int24 public constant TICK_SPACING = 1; | ||
uint256 public constant DEFAULT_AMOUNT = 100 ether; | ||
|
||
IVoter public immutable voter = IVoter(Base.VOTER); | ||
uint160 public immutable initialPriceX96 = TickMath.getSqrtRatioAtTick(0); | ||
ICLPoolFactory public immutable poolFactory = ICLPoolFactory(Base.CLPOOL_FACTORY); | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- CONTRACTS & INTERFACES | ||
//////////////////////////////////////////////////////////////// | ||
ERC20 public token0; // OETHb | ||
ERC20 public token1; // WETH | ||
ERC20 public rewardToken; | ||
|
||
ICLPool public pool; | ||
ICLGauge public gauge; | ||
INonfungiblePositionManager public nftManager; | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- STATE VARIABLES | ||
//////////////////////////////////////////////////////////////// | ||
uint256 public liquidityRatio = 8e17; // 80% OETHb, 20% WETH | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- SETUP | ||
//////////////////////////////////////////////////////////////// | ||
function setUp() public virtual { | ||
// 1. Create fork | ||
vm.createSelectFork("base", 17906760); | ||
|
||
// 2. Create Tokens | ||
token0 = ERC20(new MockERC20("Origin ETH Base", "OETHb", 18)); | ||
token1 = ERC20(new MockERC20("Wrapped ETH", "WETH", 18)); | ||
rewardToken = ERC20(new MockERC20("Reward Token", "RT", 18)); | ||
if (token1 < token0) (token0, token1) = (token1, token0); // Needed for pool address computing | ||
|
||
// 3. Whitelist token0 and token1 in Voter | ||
vm.startPrank(Base.GOV_VOTER); | ||
voter.whitelistToken(address(token0), true); | ||
voter.whitelistToken(address(token1), true); | ||
vm.stopPrank(); | ||
|
||
// 4. Create Pool | ||
pool = ICLPool( | ||
poolFactory.createPool({ | ||
tokenA: address(token0), | ||
tokenB: address(token1), | ||
tickSpacing: TICK_SPACING, | ||
sqrtPriceX96: initialPriceX96 | ||
}) | ||
); | ||
|
||
// 5. Create Gauge | ||
gauge = ICLGauge(payable(voter.createGauge({_poolFactory: address(poolFactory), _pool: address(pool)}))); | ||
nftManager = INonfungiblePositionManager(payable(pool.nft())); | ||
|
||
// 6. Max approve all tokens | ||
token0.approve(address(pool), type(uint256).max); | ||
token1.approve(address(pool), type(uint256).max); | ||
token0.approve(address(nftManager), type(uint256).max); | ||
token1.approve(address(nftManager), type(uint256).max); | ||
nftManager.setApprovalForAll(address(gauge), true); | ||
|
||
// 7. Label contracts | ||
vm.label(address(token0), "OETHb"); | ||
vm.label(address(token1), "WETH"); | ||
vm.label(address(rewardToken), "Reward Token"); | ||
vm.label(address(pool), "CLPool OETHb/WETH"); | ||
vm.label(address(gauge), "CLGauge OETHb/WETH"); | ||
vm.label(address(nftManager), "NFTManager"); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- CALLBACK | ||
//////////////////////////////////////////////////////////////// | ||
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.25; | ||
|
||
// Solmate | ||
import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; | ||
|
||
// Internal for testing | ||
import {Actions} from "test/Actions.sol"; | ||
|
||
contract Simulator is Actions { | ||
using FixedPointMathLib for uint256; | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- SETUP | ||
//////////////////////////////////////////////////////////////// | ||
function setUp() public virtual override { | ||
super.setUp(); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////// | ||
/// --- SIMULATION | ||
//////////////////////////////////////////////////////////////// | ||
function test1() public { | ||
(uint256 tokenId,) = | ||
addLiquidity(DEFAULT_AMOUNT.mulWadDown(liquidityRatio), DEFAULT_AMOUNT.mulWadUp(1e18 - liquidityRatio)); | ||
stake(tokenId); | ||
swap(address(token0), 10 ether); | ||
nftManager.positions(tokenId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.