This commit is contained in:
giteadmin 2024-12-09 23:08:24 +01:00
parent 67989416b5
commit 5db3ecb3d7
4 changed files with 163 additions and 50 deletions

View file

@ -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
}

View file

@ -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": ""
}]
}

View file

@ -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);
}
}
}