DiceRandomHook
EthereumDiceRandomHook is a Uniswap v4 hook on Ethereum. Runs code on every swap. Can take tokens from swaps. Sets its own swap fee. Runs at pool creation.
- Contract name
- DiceRandomHook
How this hook works
Trading taxA trading tax hook. It changes its fee with the market, takes a tax on trades and burns tokens.
Fee changes with the market
Instead of a fixed fee, it picks the fee on every trade: higher when the price moves fast or drifts from its target, lower when things are calm.
The code that does this (beforeSwap):function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata) external onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) { if (params.amountSpecified >= 0) revert ExactOutputUnsupported(); PoolId id = key.toId(); PoolInfo storage p = _info(id); if (!params.zeroForOne) { // Sell: fixed policy, no roll. The platform fee is taken from the ETH output in afterSwap. (uint24 sf, int24 drop, bool armed) = _sellFee(id); emit SellPolicy(id, sf, drop, armed); return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, sf | LPFeeLibrary.OVERRIDE_FEE_FLAG); } // The hook's own buy-back-and-burn (BURN rolls) and the platform buyback: no dice or platform fee, // no roll, no launch cap. Platform money must never pay out a rebate or a CLOCK pot to whoever // triggered the swap (tx.origin). if (sender == address(this) || sender == _platformRecipient) { return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, BASE_FEE | LPFeeLibrary.OVERRIDE_FEE_FLAG); } uint256 amountIn = uint256(-params.amountSpecified); address buyer = _buyerOf(sender); RandomConfig storage c = _configs[id]; if (block.timestamp < uint256(p.launchedAt) + c.guardWindow) { uint256 bought = _boughtInWindow[id][buyer] + amountIn; if (bought > c.guardMaxBuy) revert LaunchCapExceeded(bought, c.guardMaxBuy); _boughtInWindow[id][buyer] = bought; } // …Takes a tax on trades
On top of the normal pool fee, it keeps part of each trade as a tax. Buys and sells can be taxed differently.
The code that does this (beforeSwap):function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata) external onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) { if (params.amountSpecified >= 0) revert ExactOutputUnsupported(); PoolId id = key.toId(); PoolInfo storage p = _info(id); if (!params.zeroForOne) { // Sell: fixed policy, no roll. The platform fee is taken from the ETH output in afterSwap. (uint24 sf, int24 drop, bool armed) = _sellFee(id); emit SellPolicy(id, sf, drop, armed); return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, sf | LPFeeLibrary.OVERRIDE_FEE_FLAG); } // The hook's own buy-back-and-burn (BURN rolls) and the platform buyback: no dice or platform fee, // no roll, no launch cap. Platform money must never pay out a rebate or a CLOCK pot to whoever // triggered the swap (tx.origin). if (sender == address(this) || sender == _platformRecipient) { return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, BASE_FEE | LPFeeLibrary.OVERRIDE_FEE_FLAG); } uint256 amountIn = uint256(-params.amountSpecified); address buyer = _buyerOf(sender); RandomConfig storage c = _configs[id]; if (block.timestamp < uint256(p.launchedAt) + c.guardWindow) { uint256 bought = _boughtInWindow[id][buyer] + amountIn; if (bought > c.guardMaxBuy) revert LaunchCapExceeded(bought, c.guardMaxBuy); _boughtInWindow[id][buyer] = bought; } // …Burns tokens
It destroys some tokens (or sends them to an address nobody controls), so there are fewer of them.
The code that does this (unlockCallback):function unlockCallback(bytes calldata data) external onlyPoolManager returns (bytes memory) { (uint8 action, bytes memory inner) = abi.decode(data, (uint8, bytes)); if (action == ACTION_REDEEM) { (Currency c, address to, uint256 amount) = abi.decode(inner, (Currency, address, uint256)); poolManager().burn(address(this), c.toId(), amount); poolManager().take(c, to, amount); return ""; } // FLOOR reinforcement and buy-back-and-burn live in the modules; run them on this storage. (bool ok, bytes memory ret) = module.delegatecall(abi.encodeWithSignature("unlockAction(uint8,bytes)", action, inner)); if (!ok) { assembly ("memory-safe") { revert(add(ret, 32), mload(ret)) } } return abi.decode(ret, (bytes)); }Launch protection
Around launch it limits trading, for example a max buy or wallet size or a cooldown, to stop bots grabbing the supply before real traders.
The code that does this (beforeSwap):function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata) external onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) { if (params.amountSpecified >= 0) revert ExactOutputUnsupported(); PoolId id = key.toId(); PoolInfo storage p = _info(id); if (!params.zeroForOne) { // Sell: fixed policy, no roll. The platform fee is taken from the ETH output in afterSwap. (uint24 sf, int24 drop, bool armed) = _sellFee(id); emit SellPolicy(id, sf, drop, armed); return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, sf | LPFeeLibrary.OVERRIDE_FEE_FLAG); } // The hook's own buy-back-and-burn (BURN rolls) and the platform buyback: no dice or platform fee, // no roll, no launch cap. Platform money must never pay out a rebate or a CLOCK pot to whoever // triggered the swap (tx.origin). if (sender == address(this) || sender == _platformRecipient) { return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, BASE_FEE | LPFeeLibrary.OVERRIDE_FEE_FLAG); } uint256 amountIn = uint256(-params.amountSpecified); address buyer = _buyerOf(sender); RandomConfig storage c = _configs[id]; if (block.timestamp < uint256(p.launchedAt) + c.guardWindow) { uint256 bought = _boughtInWindow[id][buyer] + amountIn; if (bought > c.guardMaxBuy) revert LaunchCapExceeded(bought, c.guardMaxBuy); _boughtInWindow[id][buyer] = bought; } // …Rewards to claim
It keeps track of rewards to be claimed later.
Who controls it: No admin functions: nobody can change its rules after deployment.
Based on the hook’s published code.
What it can do
Its code executes inside each trade in pools that use it.
It can take or add tokens during a swap. Fees, burns and custom curves work this way, and so do scams.
Pools using it let the hook choose the swap fee instead of a fixed tier.
It runs when a pool is created, often to lock in that pool’s settings.
Hook history
- Platform fee 9 times
Latest transactions
- 0x31928499…597c4f block 26,377,996
- 0x5ec4cad5…5fe311 block 26,377,867
- 0x9bee1914…d35be6 block 26,377,820
- 0x83d99902…02ddff block 26,377,798
- 0x72af8881…8396f3 block 26,377,780
- 0x7ef6fc65…630707 block 26,377,779
- 0xcd90a35b…4ea0fe block 26,377,779
- 0x517b55b5…195120 block 26,377,774
- 0x3c2c66b4…81ef88 block 26,377,766
- Buy rolled 7 times
Latest transactions
- 0x5ec4cad5…5fe311 block 26,377,867
- 0x9bee1914…d35be6 block 26,377,820
- 0x83d99902…02ddff block 26,377,798
- 0x7ef6fc65…630707 block 26,377,779
- 0xcd90a35b…4ea0fe block 26,377,779
- 0x517b55b5…195120 block 26,377,774
- 0x3c2c66b4…81ef88 block 26,377,766
- Roll resolved 7 times
Latest transactions
- 0xd82491e7…58dcc7 block 26,377,881
- 0x7ae36805…342db3 block 26,377,832
- 0x4fbfeea1…706e6a block 26,377,811
- 0x3361bdb4…fb094c block 26,377,784
- 0x3361bdb4…fb094c block 26,377,784
- 0x3361bdb4…fb094c block 26,377,784
- 0xdbb0a77b…57d0ca block 26,377,776
- Rolls requested 5 times
Latest transactions
- 0xfbd20250…18ead0 block 26,377,872
- 0xbdc85afc…979f4a block 26,377,824
- 0x39d068dd…3c9863 block 26,377,803
- 0xe402521c…8146a3 block 26,377,779
- 0x37d2bfbe…8be6fb block 26,377,770
- Reserved 5 times
Latest transactions
- 0xd82491e7…58dcc7 block 26,377,881
- 0x4fbfeea1…706e6a block 26,377,811
- 0x3361bdb4…fb094c block 26,377,784
- 0x3361bdb4…fb094c block 26,377,784
- 0xdbb0a77b…57d0ca block 26,377,776
- Rolls ready 5 times
Latest transactions
- 0x18c5690d…a1c4f7 block 26,377,877
- 0x146ef64b…64a0b7 block 26,377,829
- 0xe8f91e84…dd44bd block 26,377,809
- 0xeb94edae…6b79d4 block 26,377,783
- 0xae86ef7e…419593 block 26,377,775
- Surge armed 2 times
Latest transactions
- 0xd82491e7…58dcc7 block 26,377,881
- 0x3361bdb4…fb094c block 26,377,784
- Rebated 2 times
Latest transactions
- 0x4fbfeea1…706e6a block 26,377,811
- 0x3361bdb4…fb094c block 26,377,784
- Sell policy 2 times
Latest transactions
- 0x31928499…597c4f block 26,377,996
- 0x72af8881…8396f3 block 26,377,780
- Accrued 1 time
Settings changes: set up (2 times).
Counted from what the hook recorded on-chain across all its pools, for every action in its published code, plus token transfers in and out of it.