wip
This commit is contained in:
parent
67989416b5
commit
5db3ecb3d7
4 changed files with 163 additions and 50 deletions
|
|
@ -24,13 +24,7 @@ library UniswapHelpers {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Initializes a Uniswap V3 pool with the price of 1 cent per ETH or 1 ETH in terms of token price.
|
||||
* @dev Uses the square root of the price to initialize the pool with proper scaling.
|
||||
* @param _pool The address of the Uniswap V3 pool to initialize.
|
||||
* @param token0isWeth A boolean indicating if WETH is token0 in the pool.
|
||||
*/
|
||||
function initializePoolFor1Cent(IUniswapV3Pool _pool, bool token0isWeth) internal {
|
||||
function calcPriceFor1Cent(bool token0isWeth) public pure returns (uint160 sqrtPriceX96) {
|
||||
uint256 price;
|
||||
if (token0isWeth) {
|
||||
// ETH as token0, so we are setting the price of 1 ETH in terms of token1 (USD cent)
|
||||
|
|
@ -42,8 +36,17 @@ library UniswapHelpers {
|
|||
}
|
||||
|
||||
// Calculate the square root of the price with scaling for Uniswap V3 initialization
|
||||
uint160 sqrtPriceX96 = uint160(sqrt(price) * 2**96 / 10**9);
|
||||
sqrtPriceX96 = uint160(sqrt(price) * 2**96 / 10**9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Initializes a Uniswap V3 pool with the price of 1 cent per ETH or 1 ETH in terms of token price.
|
||||
* @dev Uses the square root of the price to initialize the pool with proper scaling.
|
||||
* @param _pool The address of the Uniswap V3 pool to initialize.
|
||||
* @param token0isWeth A boolean indicating if WETH is token0 in the pool.
|
||||
*/
|
||||
function initializePoolFor1Cent(IUniswapV3Pool _pool, bool token0isWeth) internal {
|
||||
uint160 sqrtPriceX96 = calcPriceFor1Cent(token0isWeth);
|
||||
// Initialize the pool with the calculated price
|
||||
_pool.initialize(sqrtPriceX96);
|
||||
}
|
||||
|
|
@ -75,4 +78,4 @@ library UniswapHelpers {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
|
||||
IUniswapV3Factory factory;
|
||||
Stake stakingPool;
|
||||
PoolKey private poolKey;
|
||||
LiquidityManager lm;
|
||||
address feeDestination = makeAddr("fees");
|
||||
uint256 supplyOnRecenter;
|
||||
|
|
@ -36,9 +37,9 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
int256 supplyChange;
|
||||
|
||||
struct Position {
|
||||
uint256 liquidity;
|
||||
int32 tickLower;
|
||||
int32 tickUpper;
|
||||
uint128 liquidity;
|
||||
int24 tickLower;
|
||||
int24 tickUpper;
|
||||
}
|
||||
|
||||
enum ActionType {
|
||||
|
|
@ -54,18 +55,19 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
|
||||
struct Action {
|
||||
uint256 kind; // buy, sell, snatch, unstake, paytax, recenter, mint, burn
|
||||
uint256 amount1; // x , x , x , x , x , x , ,
|
||||
uint256 amount2; // , , x , , , , ,
|
||||
uint256 amount1; // x , x , x , x , x , x , x , x
|
||||
uint256 amount2; // , , x , , , , x , x
|
||||
string position; // , , x , , , , ,
|
||||
}
|
||||
|
||||
struct Scenario {
|
||||
uint256 VWAP;
|
||||
uint256 comEthBal;
|
||||
uint256 comHarbBal;
|
||||
uint256 comStakeShare;
|
||||
Position[] liquidity; // the positions are floor, anchor, liquidity, [comPos1, comPos2 ...]
|
||||
uint160 sqrtPriceX96;
|
||||
uint256 time;
|
||||
bool token0IsWeth;
|
||||
Action[] txns;
|
||||
}
|
||||
|
||||
|
|
@ -77,8 +79,9 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
harberg = new Harberg("Harberg", "HRB", tc);
|
||||
pool = IUniswapV3Pool(factory.createPool(address(weth), address(harberg), FEE));
|
||||
|
||||
poolKey = PoolAddress.getPoolKey(address(weth), address(harberg), FEE);
|
||||
token0isWeth = address(weth) < address(harberg);
|
||||
pool.initializePoolFor1Cent(token0isWeth);
|
||||
//pool.initializePoolFor1Cent(token0isWeth);
|
||||
|
||||
stakingPool = new Stake(address(harberg));
|
||||
harberg.setStakingPool(address(stakingPool));
|
||||
|
|
@ -94,6 +97,51 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
initializeTimeSeriesCSV();
|
||||
}
|
||||
|
||||
function setUpCustomToken0(bool token0shouldBeWeth) public {
|
||||
factory = UniswapHelpers.deployUniswapFactory();
|
||||
|
||||
TwabController tc = new TwabController(60 * 60 * 24, uint32(block.timestamp));
|
||||
|
||||
bool setupComplete = false;
|
||||
uint retryCount = 0;
|
||||
while (!setupComplete && retryCount < 5) {
|
||||
// Clean slate if retrying
|
||||
if (retryCount > 0) {
|
||||
deployDummies(1); // Deploy a dummy contract to shift addresses
|
||||
}
|
||||
|
||||
weth = IWETH9(address(new WETH()));
|
||||
harberg = new Harberg("HARB", "HARB", tc);
|
||||
|
||||
// Check if the setup meets the required condition
|
||||
if (token0shouldBeWeth == address(weth) < address(harberg)) {
|
||||
setupComplete = true;
|
||||
} else {
|
||||
// Clear current instances for re-deployment
|
||||
delete weth;
|
||||
delete harberg;
|
||||
retryCount++;
|
||||
}
|
||||
}
|
||||
require(setupComplete, "Setup failed to meet the condition after several retries");
|
||||
|
||||
pool = IUniswapV3Pool(factory.createPool(address(weth), address(harberg), FEE));
|
||||
|
||||
token0isWeth = address(weth) < address(harberg);
|
||||
stake = new Stake(address(harberg));
|
||||
harberg.setStakingPool(address(stake));
|
||||
Sentimenter senti = Sentimenter(address(new MockSentimenter()));
|
||||
senti.initialize(address(harberg), address(stake));
|
||||
lm = new LiquidityManager(address(factory), address(weth), address(harberg), address(senti));
|
||||
lm.setFeeDestination(feeDestination);
|
||||
vm.prank(feeDestination);
|
||||
harberg.setLiquidityManager(address(lm));
|
||||
harberg.setLiquidityPool(address(pool));
|
||||
vm.deal(address(lm), 10 ether);
|
||||
initializePositionsCSV(); // Set up the CSV header
|
||||
}
|
||||
|
||||
|
||||
function buy(uint256 amountEth) internal {
|
||||
performSwap(amountEth, true);
|
||||
}
|
||||
|
|
@ -209,12 +257,24 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
}
|
||||
|
||||
function testGeneration() public {
|
||||
// for each member of the generation, run all scenarios
|
||||
string memory json = vm.readFile("test/data/scenarios.json");
|
||||
bytes memory data = vm.parseJson(json);
|
||||
Scenario memory scenario = abi.decode(data, (Scenario));
|
||||
|
||||
vm.deal(account, scenario.comEthBal * 10**18);
|
||||
Scenario memory scenario = abi.decode(data, (Scenario));
|
||||
// vm.deal(account, scenario.comEthBal * 10**18);
|
||||
vm.prank(account);
|
||||
pool.initialize(scenario.sqrtPriceX96);
|
||||
// initialize the liquidity
|
||||
for (uint256 i = 0; i < scenario.liquidity.length; i++) {
|
||||
|
||||
pool.mint(
|
||||
address(this),
|
||||
scenario.liquidity[i].tickLower,
|
||||
scenario.liquidity[i].tickUpper,
|
||||
scenario.liquidity[i].liquidity,
|
||||
abi.encode(poolKey)
|
||||
);
|
||||
}
|
||||
weth.deposit{value: address(account).balance}();
|
||||
|
||||
for (uint256 i = 0; i < scenario.txns.length; i++) {
|
||||
|
|
@ -222,8 +282,12 @@ contract SimulationsTest is UniswapTestBase, CSVManager {
|
|||
recordState();
|
||||
}
|
||||
|
||||
//writeCsv();
|
||||
//writeCsv();
|
||||
|
||||
// for each member, combine the single results into an overall fitness core
|
||||
// apply the selection
|
||||
// apply mating
|
||||
// apply mutation
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,32 @@
|
|||
{
|
||||
"VWAP": 0,
|
||||
"comEthBal": 0,
|
||||
"comHarbBal": 0,
|
||||
"comStakeShare": 0,
|
||||
"txns": [],
|
||||
"liquidity": [{
|
||||
"liquidity": 0,
|
||||
"tickLower": -123891,
|
||||
"tickUpper": -125000
|
||||
}, {
|
||||
"liquidity": 0,
|
||||
"tickLower": -123891,
|
||||
"tickUpper": -125000
|
||||
}, {
|
||||
"liquidity": 0,
|
||||
"tickLower": -123891,
|
||||
"tickUpper": -125000
|
||||
}],
|
||||
"sqrtPriceX96": 38813714283599478074587411019430,
|
||||
"time": 0,
|
||||
"liquidity": []
|
||||
"token0IsWeth": true,
|
||||
"txns": [{
|
||||
"kind": 0,
|
||||
"amount1": 10,
|
||||
"amount2": 0,
|
||||
"position": ""
|
||||
}, {
|
||||
"kind": 1,
|
||||
"amount1": 1,
|
||||
"amount2": 0,
|
||||
"position": ""
|
||||
}]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,36 +25,36 @@ abstract contract UniswapTestBase is Test {
|
|||
* @param isBuy True if buying WETH, false if selling.
|
||||
*/
|
||||
function performSwap(uint256 amount, bool isBuy) internal {
|
||||
uint160 limit;
|
||||
// Determine the swap direction
|
||||
bool zeroForOne = isBuy ? token0isWeth : !token0isWeth;
|
||||
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);
|
||||
}
|
||||
if (isBuy) {
|
||||
vm.prank(account);
|
||||
weth.transfer(address(this), amount);
|
||||
} else {
|
||||
vm.prank(account);
|
||||
harberg.approve(address(this), amount);
|
||||
}
|
||||
|
||||
// Set the sqrtPriceLimitX96 based on the swap direction
|
||||
if (zeroForOne) {
|
||||
// Swapping token0 for token1
|
||||
// sqrtPriceLimitX96 must be less than current price but greater than MIN_SQRT_RATIO
|
||||
limit = TickMath.MIN_SQRT_RATIO + 1;
|
||||
} else {
|
||||
// Swapping token1 for token0
|
||||
// sqrtPriceLimitX96 must be greater than current price but less than MAX_SQRT_RATIO
|
||||
limit = TickMath.MAX_SQRT_RATIO - 1;
|
||||
}
|
||||
// Set the sqrtPriceLimitX96 based on the swap direction
|
||||
if (zeroForOne) {
|
||||
// Swapping token0 for token1
|
||||
// sqrtPriceLimitX96 must be less than current price but greater than MIN_SQRT_RATIO
|
||||
limit = TickMath.MIN_SQRT_RATIO + 1;
|
||||
} else {
|
||||
// Swapping token1 for token0
|
||||
// sqrtPriceLimitX96 must be greater than current price but less than MAX_SQRT_RATIO
|
||||
limit = TickMath.MAX_SQRT_RATIO - 1;
|
||||
}
|
||||
|
||||
pool.swap(
|
||||
account,
|
||||
zeroForOne,
|
||||
int256(amount),
|
||||
limit,
|
||||
abi.encode(account, int256(amount), isBuy)
|
||||
);
|
||||
pool.swap(
|
||||
account,
|
||||
zeroForOne,
|
||||
int256(amount),
|
||||
limit,
|
||||
abi.encode(account, int256(amount), isBuy)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -78,4 +78,27 @@ abstract contract UniswapTestBase is Test {
|
|||
require(harberg.transferFrom(seller, msg.sender, amountToPay), "Transfer failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Callback function that Uniswap V3 calls for liquidity actions requiring minting or burning of tokens.
|
||||
/// @param amount0Owed The amount of token0 owed for the liquidity provision.
|
||||
/// @param amount1Owed The amount of token1 owed for the liquidity provision.
|
||||
/// @dev This function mints Harberg tokens as needed and handles WETH deposits for ETH conversions during liquidity interactions.
|
||||
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
||||
// CallbackValidation.verifyCallback(factory, poolKey);
|
||||
// take care of harb
|
||||
uint256 harbPulled = token0isWeth ? amount1Owed : amount0Owed;
|
||||
if (harbPulled > 0) {
|
||||
harberg.mint(harbPulled);
|
||||
harberg.transfer(msg.sender, harbPulled);
|
||||
}
|
||||
|
||||
// pack ETH
|
||||
uint256 ethOwed = token0isWeth ? amount0Owed : amount1Owed;
|
||||
if (weth.balanceOf(address(this)) < ethOwed) {
|
||||
weth.deposit{value: address(this).balance}();
|
||||
}
|
||||
if (ethOwed > 0) {
|
||||
weth.transfer(msg.sender, amount1Owed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue