Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ ethereum_node_url: "http://localhost:8545"
chain_id: 31337 # Local development chain ID

# Contract Addresses
swap_router_address: "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf"
lp_router_address: "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF"
manager_address: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528"
hook_address: "0x2725685Ef2DefFBa748CAFF8665985BE635B8aC0"
swap_router_address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
lp_router_address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
manager_address: "0x5FbDB2315678afecb367f032d93F642f64180aa3"
hook_address: "0xD3F41c806202a1517a9B746F93B4f7cBd3468AC0"

# Account Configuration (dont update this)
private_key: "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
Expand All @@ -20,8 +20,8 @@ gas_limit: 500000
gas_price: 20 # 20 Gwei

# Token Addresses
token0_address: "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570"
token1_address: "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00"
token0_address: "0x0165878A594ca255338adfa4d48449f69242Eb8F"
token1_address: "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707"

# Pool Configuration
default_fee: 3000
Expand Down
2 changes: 1 addition & 1 deletion contracts/v4-hook/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@uniswap/v4-core/=lib/v4-core/
forge-gas-snapshot/=lib/v4-core/lib/forge-gas-snapshot/src/
forge-std/=lib/v4-core/lib/forge-std/src/
forge-std/=lib/forge-std/src/
permit2/=lib/v4-periphery/lib/permit2/
solmate/=lib/v4-core/lib/solmate/
v4-core/=lib/v4-core/
Expand Down
213 changes: 138 additions & 75 deletions contracts/v4-hook/script/Anvil.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,93 +105,156 @@ contract CounterScript is Script {
console.log("TOKEN B", address(token1));
}

function testLifecycleWithPermit(
function testLifecycleWithPermit(
IPoolManager manager,
address hook,
PoolModifyLiquidityTest lpRouter,
PoolSwapTest swapRouter
) internal {
(MOCKERC20PERMIT token0, MOCKERC20PERMIT token1) = deployTokens();

// Transfer tokens to Alice
// Mint tokens as before
token0.mint(msg.sender, 100_000 ether);
token1.mint(msg.sender, 100_000 ether);
token0.mint(alice, 100_000 ether);
token1.mint(alice, 100_000 ether);
token0.mint(address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266), 100_000 ether);
token1.mint(address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266), 100_000 ether);

// bytes memory ZERO_BYTES = new bytes(0);

// // Initialize the pool
// int24 tickSpacing = 60;
// PoolKey memory poolKey =
// PoolKey(Currency.wrap(address(token0)), Currency.wrap(address(token1)), 3000, tickSpacing, IHooks(hook));
// manager.initialize(poolKey, Constants.SQRT_PRICE_1_1, ZERO_BYTES);

token0.approve(address(lpRouter), type(uint256).max);
token1.approve(address(lpRouter), type(uint256).max);

// lpRouter.modifyLiquidity(
// poolKey,
// IPoolManager.ModifyLiquidityParams(
// TickMath.minUsableTick(tickSpacing), TickMath.maxUsableTick(tickSpacing), 100 ether, 0
// ),
// ZERO_BYTES
// );

// // Prepare swap parameters
// bool zeroForOne = true;
// int256 amountSpecified = 1 ether;
// IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
// zeroForOne: zeroForOne,
// amountSpecified: amountSpecified,
// sqrtPriceLimitX96: zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1
// });
// PoolSwapTest.TestSettings memory testSettings =
// PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});

// // Prepare permit data
// uint256 deadline = block.timestamp + 3600; // 1 hour from now
// uint256 value = uint256(amountSpecified) * 11 / 10; // Increase by 10% to account for fees and slippage

// console.log("VALUE", value);
// console.log("swap router", address(swapRouter));
// // vm.startPrank(alice);

// (uint8 v, bytes32 r, bytes32 s) = generatePermitSignature(
// IERC20Permit(address(token0)), alice, address(swapRouter), value, deadline, alicePrivateKey
// );

// // vm.stopPrank();

// console.log("Alice address:", alice);
// console.log("bob address", address(bob));

// // Perform the swap with permit (as bob, the relayer)
// vm.startBroadcast(bob);

// // Then, perform the swap on behalf of Alice
// // Call swapWithPermit
// swapRouter.swapWithPermit(
// alice, // user
// poolKey,
// params,
// testSettings,
// ZERO_BYTES, // hookData
// deadline,
// v,
// r,
// s
// );

// vm.stopBroadcast();

// // Verify the swap results (you may want to add more assertions)
// console.log("Swap completed successfully");
// console.log("Token0 balance of Alice:", token0.balanceOf(alice));
// console.log("Token1 balance of Alice:", token1.balanceOf(alice));

bytes memory ZERO_BYTES = new bytes(0);
int24 tickSpacing = 60;
PoolKey memory poolKey = PoolKey(
Currency.wrap(address(token0)),
Currency.wrap(address(token1)),
3000,
tickSpacing,
IHooks(hook)
);

manager.initialize(poolKey, Constants.SQRT_PRICE_1_1, ZERO_BYTES);

// Generate signatures for adding liquidity
console.log("\n=== ADD LIQUIDITY PERMIT PARAMETERS ===");
console.log("User Address:", alice);
console.log("Token0:", address(token0));
console.log("Token1:", address(token1));
console.log("LP Router:", address(lpRouter));

uint256 lpAmount = 100 ether;
uint256 lpDeadline = block.timestamp + 3600;
console.log("Amount:", lpAmount);
console.log("Deadline:", lpDeadline);

// Get permit signatures for both tokens for LP
(uint8 v0, bytes32 r0, bytes32 s0) = generatePermitSignature(
IERC20Permit(address(token0)),
alice,
address(lpRouter),
lpAmount,
lpDeadline,
alicePrivateKey
);

(uint8 v1, bytes32 r1, bytes32 s1) = generatePermitSignature(
IERC20Permit(address(token1)),
alice,
address(lpRouter),
lpAmount,
lpDeadline,
alicePrivateKey
);

console.log("\nToken0 Signature:");
console.log("v:", uint256(v0));
console.log("r: 0x%s", vm.toString(r0));
console.log("s: 0x%s", vm.toString(s0));

console.log("\nToken1 Signature:");
console.log("v:", uint256(v1));
console.log("r: 0x%s", vm.toString(r1));
console.log("s: 0x%s", vm.toString(s1));

console.log("\nJSON Format for Add Liquidity:");
console.log("{");
console.log(' "currency0": "%s",', address(token0));
console.log(' "currency1": "%s",', address(token1));
console.log(' "amount": "%d",', lpAmount);
console.log(' "userAddress": "%s",', alice);
console.log(' "deadline": "%d",', lpDeadline);
console.log(' "v0": %d,', uint256(v0));
console.log(' "r0": "0x%s",', vm.toString(r0));
console.log(' "s0": "0x%s",', vm.toString(s0));
console.log(' "v1": %d,', uint256(v1));
console.log(' "r1": "0x%s",', vm.toString(r1));
console.log(' "s1": "0x%s"', vm.toString(s1));
console.log("}");

// Generate swap permit signature
console.log("\n=== SWAP PERMIT PARAMETERS ===");
int256 swapAmount = 1 ether;
uint256 swapDeadline = block.timestamp + 3600;
bool zeroForOne = true;
uint256 swapNonce = token0.nonces(alice);

bytes32 SWAP_TYPEHASH = keccak256(
"SwapWithPermit(address owner,address currency0,address currency1,int256 amountSpecified,bool zeroForOne,uint256 sqrtPriceLimitX96,uint256 nonce,uint256 deadline)"
);

bytes32 domainSeparator = token0.DOMAIN_SEPARATOR();
uint256 sqrtPriceLimitX96 = zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1;

bytes32 structHash = keccak256(
abi.encode(
SWAP_TYPEHASH,
alice,
address(token0),
address(token1),
swapAmount,
zeroForOne,
sqrtPriceLimitX96,
swapNonce,
swapDeadline
)
);

bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", domainSeparator, structHash)
);

(uint8 v, bytes32 r, bytes32 s) = vm.sign(alicePrivateKey, digest);

console.log("User Address:", alice);
console.log("Token0:", address(token0));
console.log("Token1:", address(token1));
console.log("Swap Router:", address(swapRouter));
console.log("Amount:", swapAmount);
console.log("ZeroForOne:", zeroForOne);
console.log("Deadline:", swapDeadline);
console.log("\nSwap Signature:");
console.log("v:", uint256(v));
console.log("r: 0x%s", vm.toString(r));
console.log("s: 0x%s", vm.toString(s));

console.log("\nJSON Format for Swap:");
console.log("{");
console.log(' "currency0": "%s",', address(token0));
console.log(' "currency1": "%s",', address(token1));
console.log(' "amount": "%d",', swapAmount);
console.log(' "zeroForOne": %s,', zeroForOne ? "true" : "false");
console.log(' "userAddress": "%s",', alice);
console.log(' "deadline": "%d",', swapDeadline);
console.log(' "v": %d,', uint256(v));
console.log(' "r": "0x%s",', vm.toString(r));
console.log(' "s": "0x%s"', vm.toString(s));
console.log("}");

// Additional debug information
console.log("\n=== DEBUG INFORMATION ===");
console.log("Domain Separator:", uint256(domainSeparator));
console.log("Struct Hash:", uint256(structHash));
console.log("Final Digest:", uint256(digest));
console.log("Swap Nonce:", swapNonce);
console.log("SqrtPriceLimitX96:", sqrtPriceLimitX96);
}
}

function deployAndSeedTestContracts(
IPoolManager manager,
Expand Down
Loading