diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..26e8d88 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,4 @@ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ +@uniswap/v4-periphery/=lib/v4-periphery/ +@uniswap/v4-core/=lib/v4-core/ +forge-std/=lib/forge-std/src/ \ No newline at end of file diff --git a/src/HookDeployer.sol b/src/HookDeployer.sol new file mode 100644 index 0000000..c2aafa6 --- /dev/null +++ b/src/HookDeployer.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.19; + +import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; +import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; +import "forge-std/console.sol"; + +library HookDeployer { + using Hooks for IHooks; + uint256 constant CREATE2_MARKER = 0x00ff00000000000000000000000000000000000000; + + function getPrefix(Hooks.Calls memory calls) public pure returns (uint256 prefix) { + if (calls.beforeInitialize) prefix |= Hooks.BEFORE_INITIALIZE_FLAG; + if (calls.afterInitialize) prefix |= Hooks.AFTER_INITIALIZE_FLAG; + if (calls.beforeModifyPosition) prefix |= Hooks.BEFORE_MODIFY_POSITION_FLAG; + if (calls.afterModifyPosition) prefix |= Hooks.AFTER_MODIFY_POSITION_FLAG; + if (calls.beforeSwap) prefix |= Hooks.BEFORE_SWAP_FLAG; + if (calls.afterSwap) prefix |= Hooks.AFTER_SWAP_FLAG; + if (calls.beforeDonate) prefix |= Hooks.BEFORE_DONATE_FLAG; + if (calls.afterDonate) prefix |= Hooks.AFTER_DONATE_FLAG; + } + + // function mineSaltAndDeployHook(bytes memory initCode, Hooks.Calls memory calls) public returns (address, uint256) { + // console.log(getPrefix(calls)); + // (uint256 salt, address expectedAddress) = mineSaltForHookAddress(initCode, calls); + // address newAddress = deployHook(initCode, salt); + // require(newAddress == expectedAddress, "HookDeployer: UNEXPECTED_ADDRESS"); + // return (newAddress, salt); + // } + + // function mineSaltForHookAddress(bytes memory initCode, Hooks.Calls memory calls) public view returns (uint256 salt, address newAddress) { + // return _mineSaltForHookAddress(keccak256(initCode), getPrefix(calls)); + // } + + function deployHook(bytes memory initCode, uint256 salt) public returns (address newAddress) { + assembly { + newAddress := create2(0, add(initCode, 0x20), mload(initCode), salt) + } + } +} diff --git a/src/ReferenceImplementations/SaltMiner.sol b/src/ReferenceImplementations/SaltMiner.sol index 39fa9c0..91baa2e 100644 --- a/src/ReferenceImplementations/SaltMiner.sol +++ b/src/ReferenceImplementations/SaltMiner.sol @@ -9,6 +9,8 @@ contract HookMineAndSinker { /// @param initCodeHash The keccak hash of the initCode of the contract to be deployed /// @param prefix The prefix of the hook address /// @return salt The salt that will produce a hook address with the given prefix + + /// @notice SOLIDITY REFERENCE IMPLEMENTATION function mineSalt(bytes32 initCodeHash, uint256 prefix, address deployer) public view @@ -16,11 +18,11 @@ contract HookMineAndSinker { { bool valid; while (true) { - newAddress = - address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initCodeHash))))); + bytes memory toHash = abi.encodePacked(bytes1(0xff), deployer, salt, initCodeHash); + newAddress = address(uint160(uint256(keccak256(toHash)))); assembly { - valid := eq(and(newAddress, 0x00ff00000000000000000000000000000000000000), prefix) + valid := eq(and(newAddress, PREFIX_MASK), prefix) } if (valid) { break; diff --git a/test/SaltMiner.t.sol b/test/SaltMiner.t.sol index aec54bb..14e6d70 100644 --- a/test/SaltMiner.t.sol +++ b/test/SaltMiner.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.19; import "foundry-huff/HuffDeployer.sol"; import {HookDeployer} from "../src/HookDeployer.sol"; import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol"; -import {IHooks} from "@uniswap/v4-core/contracts/interfaces/IHooks.sol"; import {PoolManager} from "@uniswap/v4-core/contracts/PoolManager.sol"; import {LimitOrder} from "@uniswap/v4-periphery/contracts/hooks/examples/LimitOrder.sol"; import "forge-std/Test.sol"; @@ -41,10 +40,7 @@ contract SaltMinerTest is Test { (uint256 salt, address expectedAddress) = saltMiner.mineSalt(initCodeHash, prefix, address(this)); console.log("gas used: %s", salt); address actualAddress = HookDeployer.deployHook(initCode, salt); - - // console.log(salt); - // console.log(expectedAddress); - // console.log(actualAddress); + assertEq(actualAddress, expectedAddress); } }