pragma solidity ^0.8.26;
import {Test} from "forge-std/Test.sol";
import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol";
import {Hooks} from "v4-core/libraries/Hooks.sol";
import {HookMiner} from "v4-periphery/src/utils/HookMiner.sol";
import {LPFeeLibrary} from "v4-core/libraries/LPFeeLibrary.sol";
import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol";
import {TokenLaunchHook} from "../src/TokenLaunchHook.sol";
contract MissingAdminCapabilitiesTest is Test, Deployers {
TokenLaunchHook hook;
uint256 phase1Duration = 100;
uint256 phase2Duration = 200;
uint256 phase1LimitBps = 100;
uint256 phase2LimitBps = 300;
uint256 phase1Cooldown = 5;
uint256 phase2Cooldown = 3;
uint256 phase1PenaltyBps = 500;
uint256 phase2PenaltyBps = 200;
function setUp() public {
deployFreshManagerAndRouters();
bytes memory creationCode = type(TokenLaunchHook).creationCode;
bytes memory args = abi.encode(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_INITIALIZE_FLAG);
(address mined, bytes32 salt) = HookMiner.find(address(this), flags, creationCode, args);
hook = new TokenLaunchHook{salt: salt}(
IPoolManager(manager),
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
require(address(hook) == mined, "Hook address mismatch");
}
function test_NoAdminSetters_ImmutablesRigid() public {
uint256 d1 = hook.phase1Duration();
uint256 d2 = hook.phase2Duration();
uint256 l1 = hook.phase1LimitBps();
uint256 l2 = hook.phase2LimitBps();
uint256 c1 = hook.phase1Cooldown();
uint256 c2 = hook.phase2Cooldown();
uint256 p1 = hook.phase1PenaltyBps();
uint256 p2 = hook.phase2PenaltyBps();
(bool ok1, ) = address(hook).call(abi.encodeWithSignature("setPhase1Duration(uint256)", 999));
(bool ok2, ) = address(hook).call(abi.encodeWithSignature("setPhase2Duration(uint256)", 999));
(bool ok3, ) = address(hook).call(abi.encodeWithSignature("setPhase1LimitBps(uint256)", 9999));
(bool ok4, ) = address(hook).call(abi.encodeWithSignature("setPhase2LimitBps(uint256)", 9999));
(bool ok5, ) = address(hook).call(abi.encodeWithSignature("setPhase1Cooldown(uint256)", 0));
(bool ok6, ) = address(hook).call(abi.encodeWithSignature("setPhase2Cooldown(uint256)", 0));
(bool ok7, ) = address(hook).call(abi.encodeWithSignature("setPhase1PenaltyBps(uint256)", 0));
(bool ok8, ) = address(hook).call(abi.encodeWithSignature("setPhase2PenaltyBps(uint256)", 0));
assertFalse(ok1 || ok2 || ok3 || ok4 || ok5 || ok6 || ok7 || ok8, "unexpected setter(s) present");
assertEq(hook.phase1Duration(), d1, "phase1Duration changed unexpectedly");
assertEq(hook.phase2Duration(), d2, "phase2Duration changed unexpectedly");
assertEq(hook.phase1LimitBps(), l1, "phase1LimitBps changed unexpectedly");
assertEq(hook.phase2LimitBps(), l2, "phase2LimitBps changed unexpectedly");
assertEq(hook.phase1Cooldown(), c1, "phase1Cooldown changed unexpectedly");
assertEq(hook.phase2Cooldown(), c2, "phase2Cooldown changed unexpectedly");
assertEq(hook.phase1PenaltyBps(), p1, "phase1PenaltyBps changed unexpectedly");
assertEq(hook.phase2PenaltyBps(), p2, "phase2PenaltyBps changed unexpectedly");
}
}
- uint256 public immutable phase1Duration;
+ uint256 public phase1Duration;
- uint256 public immutable phase1LimitBps;
+ uint256 public phase1LimitBps;
// ...repeat for all eight parameters
+ // Example access control (choose what your stack uses)
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+ contract TokenLaunchHook is BaseHook, Ownable {
+ constructor(/*...*/) BaseHook(_poolManager) Ownable(msg.sender) { /* initialize params */ }
+
+ event ParamsUpdated(uint256 phase1Duration, uint256 phase2Duration, /* ... */);
+
+ function setPhase1Duration(uint256 v) external onlyOwner {
+ require(v > 0, "phase1Duration=0");
+ phase1Duration = v;
+ emit ParamsUpdated(phase1Duration, phase2Duration, /* ... */);
+ }
+ // Add similar setters with validation for each parameter
+ }