Loading...
Loading...
Deploy CCA (Continuous Clearing Auction) smart contracts using the Factory pattern. Use when user says "deploy auction", "deploy cca", "factory deployment", or wants to deploy a configured auction.
npx skill4agent add uniswap/uniswap-ai deployerContinuousClearingAuctionFactoryRuntime Compatibility: This skill usesfor interactive prompts. IfAskUserQuestionis not available in your runtime, collect the same parameters through natural language conversation instead.AskUserQuestion
--ledgerforge script script/Example.s.sol:ExampleScript \
--rpc-url $RPC_URL \
--broadcast \
--ledgercast wallet import# Import private key to encrypted keystore (one-time setup)
cast wallet import deployer --interactive
# Use keystore for deployment
forge script script/Example.s.sol:ExampleScript \
--rpc-url $RPC_URL \
--broadcast \
--account deployer \
--sender $DEPLOYER_ADDRESS.envsource .envdotenv# .env file (add to .gitignore)
PRIVATE_KEY=0x...
RPC_URL=https://...
# Load environment
source .env
# Deploy
forge script ... --private-key $PRIVATE_KEYContinuousClearingAuctionFactory| Version | Address | Status |
|---|---|---|
| v1.1.0 | | Recommended |
git clone https://github.com/Uniswap/continuous-clearing-auction.git
cd continuous-clearing-auction
forge installconfigurator{
"1": {
"token": "0x...",
"totalSupply": 1e29,
"currency": "0x0000000000000000000000000000000000000000",
"tokensRecipient": "0x...",
"fundsRecipient": "0x...",
"startBlock": 24321000,
"endBlock": 24327001,
"claimBlock": 24327001,
"tickSpacing": 79228162514264337593543950,
"validationHook": "0x0000000000000000000000000000000000000000",
"floorPrice": 7922816251426433759354395000,
"requiredCurrencyRaised": 0,
"supplySchedule": [
{ "mps": 1000, "blockDelta": 6000 },
{ "mps": 4000000, "blockDelta": 1 }
]
}
}function initializeDistribution(
address token,
uint256 amount,
bytes calldata configData,
bytes32 salt
) external returns (IDistributionContract);tokenamountconfigDataAuctionParameterssaltinitializeDistributionconfigDataAuctionParameters# Encode the AuctionParameters struct
cast abi-encode "initializeDistribution(address,uint256,bytes,bytes32)" \
"$TOKEN_ADDRESS" \
"$TOTAL_SUPPLY" \
"$(cast abi-encode "(address,address,address,uint64,uint64,uint64,uint256,address,uint256,uint128,bytes)" \
"$CURRENCY" \
"$TOKENS_RECIPIENT" \
"$FUNDS_RECIPIENT" \
"$START_BLOCK" \
"$END_BLOCK" \
"$CLAIM_BLOCK" \
"$TICK_SPACING" \
"$VALIDATION_HOOK" \
"$FLOOR_PRICE" \
"$REQUIRED_CURRENCY_RAISED" \
"$ENCODED_SUPPLY_SCHEDULE")" \
"0x0000000000000000000000000000000000000000000000000000000000000000"// script/DeployAuction.s.sol
pragma solidity ^0.8.24;
import "forge-std/Script.sol";
interface ICCAFactory {
function initializeDistribution(
address token,
uint256 amount,
bytes calldata configData,
bytes32 salt
) external returns (address);
}
contract DeployAuction is Script {
function run() external {
// Load config values
address token = vm.envAddress("TOKEN");
uint256 amount = vm.envUint("TOTAL_SUPPLY");
// Encode AuctionParameters
bytes memory configData = abi.encode(
vm.envAddress("CURRENCY"),
vm.envAddress("TOKENS_RECIPIENT"),
vm.envAddress("FUNDS_RECIPIENT"),
uint64(vm.envUint("START_BLOCK")),
uint64(vm.envUint("END_BLOCK")),
uint64(vm.envUint("CLAIM_BLOCK")),
vm.envUint("TICK_SPACING"),
vm.envAddress("VALIDATION_HOOK"),
vm.envUint("FLOOR_PRICE"),
uint128(vm.envUint("REQUIRED_CURRENCY_RAISED")),
vm.envBytes("ENCODED_SUPPLY_SCHEDULE")
);
vm.startBroadcast();
// Approve token transfer to factory
IERC20(token).approve(
0xCCccCcCAE7503Cac057829BF2811De42E16e0bD5,
amount
);
// Deploy auction
address auction = ICCAFactory(
0xCCccCcCAE7503Cac057829BF2811De42E16e0bD5
).initializeDistribution(
token,
amount,
configData,
bytes32(0) // salt
);
vm.stopBroadcast();
console.log("Auction deployed at:", auction);
}
}initializeDistributionamount# Deploy factory (if needed on new network)
forge script script/deploy/DeployContinuousAuctionFactory.s.sol:DeployContinuousAuctionFactoryScript \
--rpc-url $RPC_URL \
--broadcast \
--private-key $PRIVATE_KEY
# Deploy auction instance
forge script script/Example.s.sol:ExampleScript \
--rpc-url $RPC_URL \
--broadcast \
--private-key $PRIVATE_KEYonTokensReceived()cast send $AUCTION_ADDRESS "onTokensReceived()" --rpc-url $RPC_URL --private-key $PRIVATE_KEYconstructor(
address token,
uint128 amount,
AuctionParameters memory parameters
) {}forge verify-contract $AUCTION_ADDRESS \
src/ContinuousClearingAuction.sol:ContinuousClearingAuction \
--rpc-url $RPC_URL \
--show-standard-json-input > standard-json-input.jsonstartBlock < endBlock <= claimBlocklibrary FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000; // 2^96
}uint64mpsblockDeltafunction parse(bytes8 data) internal pure returns (uint24 mps, uint40 blockDelta) {
mps = uint24(bytes3(data));
blockDelta = uint40(uint64(data));
}maxPriceamountownerprevTickPricehookDatacurrencyRaised >= requiredCurrencyRaisedclaimBlocksweepCurrency()sweepUnsoldTokens()| Chain ID | Network | Block Time |
|---|---|---|
| 1 | Mainnet | 12s |
| 130 | Unichain | 1s |
| 1301 | Unichain Sepolia | 2s |
| 8453 | Base | 2s |
| 42161 | Arbitrum | 2s |
| 11155111 | Sepolia | 12s |
| Issue | Solution |
|---|---|
| "Invalid block sequence" | Ensure startBlock < endBlock <= claimBlock |
| "Floor price not aligned" | Round floor price to multiple of tick spacing |
| "Tick spacing too small" | Use at least 1% of floor price |
| "Total supply too large" | Max 1e30 wei (1 trillion 18-decimal tokens) |
| "Gas inefficiency" | Increase tick spacing |
| "Invalid address" | Verify addresses are 42 characters starting with 0x |
onTokensReceived()docs/TechnicalDocumentation.mddocs/DeploymentGuide.mddocs/assets/whitepaper.pdfdocs/audits/README.md