Vanguard

First Flight #56
Beginner FriendlyDeFiFoundry
0 EXP
Submission Details
Impact: high
Likelihood: high

Deploy script initialize with wrong flag

Author Revealed upon completion

Deploy script is initialize with wrong flag

Description

Because of encoded addresses, hook developers must mine an address to a their particular pattern. Mine the address by finding a salt that produces a hook address with the desired flags, use the Foundry deterministic deployer when deploying via Foundry script.

Inside deployLaunchHool.s.sol wrong flag is initialized for the intended hook

function run() public {
// hook contracts must have specific flags encoded in the address
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG); // <@ wrong flag here
// Mine a salt that will produce a hook address with the correct flags
bytes memory constructorArgs = abi.encode(
poolManager,
PHASE1_DURATION,
PHASE2_DURATION,
PHASE1_LIMIT_BPS,
PHASE2_LIMIT_BPS,
PHASE1_COOLDOWN,
PHASE2_COOLDOWN,
PHASE1_PENALTY_BPS,
PHASE2_PENALTY_BPS
);
(address hookAddress, bytes32 salt) =
HookMiner.find(CREATE2_FACTORY, flags, type(TokenLaunchHook).creationCode, constructorArgs);
// other codes

Risk

Failed to deploy to desired chain

Likelihood:

  • It will always occurs whenever protocol is deployed with the current script

Impact:

  • Protocol will be failed to be deployed

Proof of Concept

Inside current test suite TokenLaunchHookUnit.t.sol change flag on lines 76.

Run test suite with forge test

contract TestTokenLaunchHook is Test, Deployers, ERC1155TokenReceiver {
MockERC20 token;
TokenLaunchHook public antiBotHook;
Currency ethCurrency = Currency.wrap(address(0));
Currency tokenCurrency;
address user1 = address(0x1);
address user2 = address(0x2);
address bot1 = address(0xB0B1);
address bot2 = address(0xB0B2);
uint160 constant SQRT_PRICE_1_1_s = 79228162514264337593543950336;
uint256 phase1Duration = 100;
uint256 phase2Duration = 100;
uint256 phase1LimitBps = 100;
uint256 phase2LimitBps = 500;
uint256 phase1Cooldown = 5;
uint256 phase2Cooldown = 2;
uint256 phase1PenaltyBps = 1000;
uint256 phase2PenaltyBps = 500;
function setUp() public {
deployFreshManagerAndRouters();
token = new MockERC20("TOKEN", "TKN", 18);
tokenCurrency = Currency.wrap(address(token));
token.mint(address(this), 1000 ether);
token.mint(user1, 1000 ether);
token.mint(user2, 1000 ether);
token.mint(bot1, 1000 ether);
token.mint(bot2, 1000 ether);
bytes memory creationCode = type(TokenLaunchHook).creationCode;
bytes memory constructorArgs = abi.encode(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
// CHANGE INTO THE WRONG FLAG
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
(address hookAddress, bytes32 salt) = HookMiner.find(address(this), flags, creationCode, constructorArgs);
antiBotHook = new TokenLaunchHook{salt: salt}(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
require(address(antiBotHook) == hookAddress, "Hook address mismatch");
// other codes

Log output

andrea@Andreas-MacBook-Pro 2026-01-vanguard % forge test
[⠊] Compiling...
[⠊] Compiling 1 files with Solc 0.8.26
[⠒] Solc 0.8.26 finished in 60.52s
Compiler run successful!
Ran 1 test for test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook
[FAIL: HookAddressNotValid(0x30c125944809F47AF300cDB99D9181731687a080)] setUp() (gas: 0)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 262.44ms (0.00ns CPU time)
Ran 1 test suite in 371.93ms (262.44ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook
[FAIL: HookAddressNotValid(0x30c125944809F47AF300cDB99D9181731687a080)] setUp() (gas: 0)
Encountered a total of 1 failing tests, 0 tests succeeded

Recommended Mitigation

Switch code to correct flag

function run() public {
// hook contracts must have specific flags encoded in the address
- uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
+ uint160 flags = uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG);
// Mine a salt that will produce a hook address with the correct flags
bytes memory constructorArgs = abi.encode(
poolManager,
PHASE1_DURATION,
PHASE2_DURATION,
PHASE1_LIMIT_BPS,
PHASE2_LIMIT_BPS,
PHASE1_COOLDOWN,
PHASE2_COOLDOWN,
PHASE1_PENALTY_BPS,
PHASE2_PENALTY_BPS
);
(address hookAddress, bytes32 salt) =
HookMiner.find(CREATE2_FACTORY, flags, type(TokenLaunchHook).creationCode, constructorArgs);

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!