A Uniswap V4 hook that uses Chainlink VRF for asynchronous randomized swaps
AsyncSwap is a Uniswap V4 hook with the following pillars:
- VRF-powered mechanics – Chainlink VRF drives every swap outcome so randomness is verifiable.
- Two execution modes – starts on a Pump.fun-style bonding curve, then auto-migrates to standard Uniswap V4 liquidity once the ETH raised crosses the graduation threshold.
- Pluggable game logic – the current Smuggler module rolls buys between Clean Run (40%), Ambush (30% burns 15-50%), and Drop Spotted (30% bonus mint) while sells roll between DEI (40% cancel + cooldown), Ambush (30% pre-swap burn), and Drop Spotted (30% pre-swap mint); any other
IGameMechanicscontract can be dropped in. - Referral system – swaps feed a shared referral contract so creators can reward promoters across every hook deployment.
BamboozleHook.sol– the async swap hook that runs the bonding curve, VRF mechanics, and Uniswap V4 migration logic end to end.BamboozleHookFactory.sol– thin CREATE2 factory the launchpad uses to deploy hooks with pre-mined salts.BamboozleLaunchpad.sol– orchestrates token deployments, wires VRF config, seeds the pool, and hands ownership to the hook in one transaction.BamboozleToken.sol– ERC20 with mint/burn/cooldown roles so mechanics can add bonus supply, burn ambush losses, or freeze sellers.ReferralManager.sol– shared referral + fee splitter that tracks referrers across hooks and pays them from swap fees.
Deployed on: Base Sepolia & Base Mainnet
This template is designed to work with Foundry (stable). If you are using Foundry Nightly, you may encounter compatibility issues. You can update your Foundry installation to the latest stable version by running:
foundryup
To set up the project, run the following commands in your terminal to install dependencies and run the tests:
forge install
forge test
Deployment scripts are available in script/ directory:
00_DeployHook.s.sol- Deploy AsyncSwap hook with Chainlink VRF configuration01_CreatePoolAndAddLiquidity.s.sol- Create pool and add initial liquidity02_WhitelistPool.s.sol- Whitelist the pool for async swaps03_Swap.s.sol- Execute a swap that triggers VRF requestFulfillSwap.s.sol- Manually fulfill pending swap (emergency use if automatic fulfillment fails)04_MultiSwap.s.sol- Execute multiple swaps
Scripts support both local anvil environment and production networks (Base Sepolia, Base Mainnet).
- Start Anvil (or fork a specific chain using anvil):
anvilor
anvil --fork-url <YOUR_RPC_URL>- Execute scripts:
forge script script/00_DeployHook.s.sol \
--rpc-url http://localhost:8545 \
--private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d \
--broadcast:::info
It is best to not store your private key even in .env or enter it directly in the command line. Instead use the --account flag to select your private key from your keystore.
:::
Details
- Add your private key to the keystore:
cast wallet import <SET_A_NAME_FOR_KEY> --interactive- You will prompted to enter your private key and set a password, fill and press enter:
Enter private key: <YOUR_PRIVATE_KEY>
Enter keystore password: <SET_NEW_PASSWORD>
You should see this:
`<YOUR_WALLET_PRIVATE_KEY_NAME>` keystore was saved successfully. Address: <YOUR_WALLET_ADDRESS>
::: warning
Use history -c to clear your command history.
:::
- Execute scripts:
forge script script/00_DeployHook.s.sol \
--rpc-url <YOUR_RPC_URL> \
--account <YOUR_WALLET_PRIVATE_KEY_NAME> \
--sender <YOUR_WALLET_ADDRESS> \
--broadcastYou will prompted to enter your wallet password, fill and press enter:
Enter keystore password: <YOUR_PASSWORD>
Before deployment, update script/base/BaseScript.sol:
-
Chainlink VRF Configuration:
subscriptionId- Your Chainlink VRF subscription IDkeyHash- Gas lane key hash for your networkcallbackGasLimit- Gas limit for VRF callback (default: 500,000)
-
Pool Configuration:
token0andtoken1- Token addresses for your poolpoolFee- Pool fee tier (e.g., 3000 for 0.3%)tickSpacing- Tick spacing for the pool
-
Liquidity Settings:
- Update amounts in
01_CreatePoolAndAddLiquidity.s.sol
- Update amounts in
AsyncSwap uses REQUEST_CONFIRMATIONS = 0 on Base for fastest VRF response (~4 seconds):
- Only allowed on AVAX, Base, OP, and Soneium (centralized sequencer chains)
- Chainlink reads from L2 blocks, not flashblocks
- VRF generation (2-4s) is slower than block finalization (~2s)
- Base has 0 documented L2 block reorgs since launch (2+ years)
- Trade-off: <0.01% theoretical risk for 2-4 second UX improvement
Details
When installing dependencies with forge install, Github may throw a Permission Denied error
Typically caused by missing Github SSH keys, and can be resolved by following the steps here
Or adding the keys to your ssh-agent, if you have already uploaded SSH keys
Some versions of Foundry may limit contract code size to ~25kb, which could prevent local tests to fail. You can resolve this by setting the code-size-limit flag
anvil --code-size-limit 40000
Hook deployment failures are caused by incorrect flags or incorrect salt mining
- Verify the flags are in agreement:
getHookCalls()returns the correct flagsflagsprovided toHookMiner.find(...)
- Verify salt mining is correct:
- In forge test: the deployer for:
new Hook{salt: salt}(...)andHookMiner.find(deployer, ...)are the same. This will beaddress(this). If usingvm.prank, the deployer will be the pranking address - In forge script: the deployer must be the CREATE2 Proxy:
0x4e59b44847b379578588920cA78FbF26c0B4956C- If anvil does not have the CREATE2 deployer, your foundry may be out of date. You can update it with
foundryup
- If anvil does not have the CREATE2 deployer, your foundry may be out of date. You can update it with
- In forge test: the deployer for:
The project includes comprehensive stress tests to validate the bonding curve and game mechanics:
forge test1000 Cycles Stress Test (detailed output):
TIMESTAMP=$(date +%s) forge test --match-test "test_3_StressTest_1000Cycles" -vvvStop at Migration Test (runs until migration or error):
TIMESTAMP=$(date +%s) forge test --match-test test_4_StressTest_StopAtMigration -vvMigration With Pending Swap (ensures pending swaps are handled safely before migration):
TIMESTAMP=$(date +%s) forge test --match-test test_Migration_WithPendingSwap -vvRun the automated meta-analysis script to execute 500 independent test runs and aggregate statistics:
./scripts/meta_analysis.shThis will provide:
- Migration vs Error distribution
- Average cycles per outcome
- Mechanic distribution (mint/burn percentages)
- Net token effects (minted vs burned)
- Net ETH flow analysis
The meta-analysis runs the test_4_StressTest_StopAtMigration test 500 times with different VRF seeds to validate that game mechanics are balanced and fair across many scenarios.
Uniswap V4:
Chainlink VRF:
Base: