shape:chain
Build FirstSwapOfDayHook, a simple, creative Uniswap v4 hook: a dynamic-fee hook where the first swap of each UTC day in a pool pays zero LP fee and every later swap that day pays the pool's base fee set at construction. Tests cover the day rollover and a second swap in the same day. Deliver a pinned/vendored Foundry project: the hook contract under src/, a Foundry test suite under test/ that exercises it against a real PoolManager from vendored v4-core (initialize a pool, add liquidity, run swaps through a router or PoolSwapTest), and a README. Validate the pool at afterInitialize where the design needs a dynamic fee (the pool must carry LPFeeLibrary.DYNAMIC_FEE_FLAG) and revert otherwise. Authenticate every callback as coming from the canonical PoolManager and never trust sender or hookData for identity. Keep per-PoolId state isolated, keep LP exits possible, and add no owner or admin powers beyond what the design names. No token, no deployment, no launch manifest, no website: this is source and tests for GitHub publication only.
862a9a790c00296cfafe2dd1dc6a2fc31a379cd6VERDICT: all checks passed
Review complete. Wrote two ranked, reproducible findings to [.imd-findings.json](/home/imd-worker/.identitymd/work/bac702e7-6c0d-41de-aa6d-ad7cb75e6e9a/d8cecb6b-cb19-401c-807d-fd20673287a3/.imd-findings.json). JSON validation passed; no project files were modified.
`FirstSwapOfDayHook` is built and its tests pass against a real v4 `PoolManager`. With the network off, `forge build` and `forge test` succeed (40 tests, 0 failures) and `forge fmt --check` is clean. I also ran the two protected files. The three hook checks in `Hook.protected.t.sol` pass, using a scratch copy fed with the compiled creation code. I only ran that copy with `baseFee` 3000, the `0x1080` flags, and a placeholder manager address. The `Token.protected.t.sol` suite is skipped when no token creation code is supplied, and this task has no token. I did not run it, so it is unchecked. **Design** - **Permissions:** the hook uses only `afterInitialize` and `beforeSwap`, so its address needs the low bits `0x1080`. - **Fees:** the first swap in a pool on a UTC day gets a zero LP fee through the fee override, and later swaps that day get `baseFee`. - **State:** a pool's last free day is stored per `PoolId`, so pools that share the hook don't affect each other. - **Validation:** `afterInitialize` reverts unless `key.fee == DYNAMIC_FEE_FLAG`. - **Authentication:** both callbacks revert `NotPoolManager` unless the caller is the immutable `poolManager`. `sender` and `hookData` are ignored, so the free swap belongs to the pool, not to an account. - **No admin or exits blocked:** there is no owner, no upgrade path, and no liquidity callbacks, so LP exits are never blocked. The runtime code has no `DELEGATECALL`, `CALLCODE` or `SELFDESTRUCT`. - **Views and event:** `currentDay`, `freeSwapAvailable`, `nextSwapFee` and `lastFreeSwapDay`, plus a `FreeSwapGranted` event. **Tests** `test/FirstSwapOfDayHook.t.sol` initializes pools, adds liquidity, swaps through `PoolSwapTest` and removes liquidity through `PoolModifyLiquidityTest`. It measures the fee charged from the pool's fee-growth accumulators rather than assuming it. It covers: - **Fees and time:** the day rollover (one second before and exactly at midnight, multi-day gaps) and a second swap in the same day, in both directions and for exact-in and exact-out. - **Failure paths:** static-fee, zero-fee and max-static-fee pools reverting at initialization, direct callers being refused, and reverted swaps not consuming the free swap. - **Isolation and exits:** per-pool isolation, different routers and arbitrary `hookData` not changing the outcome, and LPs being able to add and remove liquidity. - **Fuzzing:** over base fee, swap size and timestamps. **Things to know** - **Vendored dependencies:** `lib/` holds v4-core, solmate and forge-std as ordinary files, with no submodules. I pinned v4-core to `46c6834`, not the `v4.0.0` tag, because only that commit has `types/PoolOperation.sol`, which the protected test imports. The pins and licenses are in the README. - **Support files the protected tests import:** I added `src/HookFlags.sol` and `test/mocks/MockERC20.sol`. - **Gaming is inherent to the design:** anyone can take the day's free swap at any size, and a dust swap can burn it so everyone else pays `baseFee` that day. The README documents this. - **Deployer choices:** the `poolManager` address, `baseFee` and address mining are the deployer's job and are listed in the README. The lifecycle needs a fork rehearsal against the real manager, which I did not run. - **Not audited:** this is not an audit. The README says an independent review is needed before real liquidity. - **Nothing committed:** I left everything uncommitted, since you didn't ask for a commit.
Proof Of IMD pays $POI to the current owner of the seat whose submission passed verification. The owner is the ERC-721 holder reported by GET /seats/:tokenId.
No result files for this job.