# DCA.fun Protocol - LLM Reference Documentation # Last Updated: 2026-01-07 # Version: 1.0.0 # Source: https://docs.dca.fun ================================================================================ SECTION 1: PROTOCOL OVERVIEW ================================================================================ ## What is DCA.fun? DCA.fun is a decentralized Dollar Cost Averaging (DCA) protocol built on Ethereum and EVM-compatible chains. It enables automated, recurring token swaps with: - Isolated vault architecture (each order has its own vault) - Yield generation through Aave V3 integration - Accurate pricing via Chainlink Data Streams - Gas-efficient minimal proxy vault deployment - Dutch auction mechanism for fair order execution ## Key Participants 1. ORDER CREATOR: Initiates DCA orders, deposits funds, earns yield, can cancel anytime 2. ORDER RECIPIENT: Receives output tokens (can be different from creator) 3. ORDER FILLER: Anyone who executes orders for profit using the Dutch auction mechanism ## Core Flow ``` User Creates Order -> Vault Deployed -> Funds Deposited -> Earn Yield (optional) Filler queries API -> Filler Executes -> Tokens Swapped -> Recipient Receives -> Repeat ``` ## Supported Networks | Network | Chain ID | Contract Address | Status | |---------------|----------|----------------------------------------------|-----------| | Base | 8453 | 0xDCA00000067413240AEaB357a3A89ea352D013E8 | Mainnet | | Base Sepolia | 84532 | 0xDCA00000067413240AEaB357a3A89ea352D013E8 | Testnet | ================================================================================ SECTION 2: SMART CONTRACT REFERENCE ================================================================================ ## Contract Architecture ``` DcaDotFun (Main Entry Point) ├── Inherits: DotFun (Price Feed Base) ├── Uses: VerifierDotFun (Chainlink Verifier) ├── Deploys via: DcaVaultFactory └── Creates: DcaVault (Per Order) External Integrations: - Chainlink Data Streams (Price feeds) - Aave V3 Pool (Yield generation) - Permit2 (Token transfers) ``` -------------------------------------------------------------------------------- ## DcaDotFun.sol - Main Protocol Contract -------------------------------------------------------------------------------- ### Order Creation Functions ```solidity function createOrder( OrderArgs calldata args, bytes[] calldata reports ) external returns (uint256 orderId) ``` Creates a new DCA order with ERC20 tokens. Parameters: - args: OrderArgs struct with order configuration - reports: Chainlink price reports for token validation Returns: orderId - Unique identifier for the created order ```solidity function createOrderNative( OrderArgs calldata args, bytes[] calldata reports ) external payable returns (uint256 orderId) ``` Creates a new DCA order using native ETH as input token (use address(0) for tokenIn). ### Order Execution Functions ```solidity function fillOrder( bytes calldata data, address recipient ) external nonReentrant whenOrderFillNotPaused ``` Direct fill: Executes an order using encoded quote data. Filler must have pre-approved Permit2. Parameters: - data: ABI-encoded quote data from the Quote API - recipient: Address to receive input tokens (usually filler's address) ```solidity function fillOrder( bytes calldata data, address callback, address initiator, address recipient ) external nonReentrant whenOrderFillNotPaused ``` Callback fill: Advanced execution with custom callback logic for flash loans and DEX aggregation. Parameters: - data: ABI-encoded quote data from the Quote API - callback: Address of callback contract implementing IFillOrderCallback - initiator: Address that initiated the fill (for callback context) - recipient: Address to receive input tokens ### Order Management Functions ```solidity function cancelOrders(uint256[] calldata orderIds) external ``` Cancels multiple orders. Only callable by order creator. Returns remaining funds to recipient. ### Query Functions ```solidity function getOrders(uint256[] calldata ids) external view returns (Order[] memory) ``` Returns order details for specified order IDs. ```solidity function quote( uint256 id, bytes[] calldata reports ) external returns (bytes memory encodedData, OrderValidation memory validation) ``` Simulates an order fill on-chain and returns execution parameters. ```solidity function getOrderTokens(uint256[] calldata ids) external view returns (OrderTokens[] memory) ``` Returns token information for specified orders including feed IDs. ```solidity function getTokenProps(address token) external view returns (TokenProps memory) ``` Returns token properties including price feed and staking status. -------------------------------------------------------------------------------- ## Data Structures -------------------------------------------------------------------------------- ### OrderArgs Struct (Order Creation Input) ```solidity struct OrderArgs { address recipient; // Who receives output tokens address tokenIn; // Input token address (address(0) for ETH) address tokenOut; // Output token address uint256 spendAmount; // Amount per execution (in token decimals) uint256 repeats; // Number of executions (must be > 0) uint256 freqInterval; // Time between executions in seconds (min ~30s) uint256 scalingInterval; // Dutch auction duration (max 300 seconds) uint256 slippage; // Max price deviation in basis points (100 = 1%) uint256 firstExecution; // Delay before first execution (0 = freqInterval) bool stakeAssetIn; // Whether to stake input in Aave bool stakeAssetOut; // Whether to stake output in Aave } ``` ### Order Struct (Order State) ```solidity struct Order { address creator; // Order creator address uint16 slippage; // Slippage tolerance in basis points bool stakeAssetIn; // Stake input flag bool stakeAssetOut; // Stake output flag address recipient; // Output recipient address tokenIn; // Input token address tokenOut; // Output token uint256 spendAmount; // Amount per fill uint256 repeats; // Remaining executions uint256 freqInterval; // Execution frequency uint256 scalingInterval; // Auction duration uint256 lastRun; // Last execution timestamp uint256 protocolFee; // Fee at creation (locked in) address vault; // Vault contract address } ``` ### OrderValidation Struct (Quote Result) ```solidity struct OrderValidation { uint256 scalingFactor; // Current scaling factor uint256 effectiveSlippage; // Actual slippage applied uint256 fillableAmount; // Amount of tokenIn fillable uint256 amountOfTokenOut; // Required output token amount uint256 inAmount; // Input amount for calculation uint256 minOutAmount; // Minimum output after slippage bool valid; // Whether order is fillable } ``` ### TokenProps Struct ```solidity struct TokenProps { bytes32 priceFeed; // Chainlink feed ID uint8 decimals; // Token decimals bool isActive; // Whether token is supported bool isStakable; // Whether token can be staked in Aave } ``` -------------------------------------------------------------------------------- ## DcaVault.sol - Isolated Vault Contract -------------------------------------------------------------------------------- Each order deploys a dedicated vault using minimal proxy (clone) pattern. ### State Variables ```solidity uint256 public orderId; // Unique order identifier uint256 public yieldSplit; // Protocol yield share (basis points) uint256 public escrow; // Accumulated output tokens uint256 public totalFills; // Number of completed fills uint256 public spendAmount; // Amount per execution address public funContract; // Main protocol contract address public feeCollector; // Protocol fee recipient address public recipient; // Order recipient address public tokenIn; // Input token address public aTokenIn; // Aave aToken for input address public tokenOut; // Output token address public aTokenOut; // Aave aToken for output address public pool; // Aave pool address bool public isCancelled; // Cancellation status ``` ### Vault Functions ```solidity function fillOrder( address recipient, uint256 amount, uint256 escrow ) external // Only callable by main contract function cancelOrder(uint256 repeats) external // Only callable by main contract function withdrawErc20(address token) external // Owner can withdraw tokens function withdrawNative() external // Owner can withdraw ETH ``` -------------------------------------------------------------------------------- ## DcaVaultFactory.sol - Vault Deployment -------------------------------------------------------------------------------- ```solidity function createVault( uint256 id, address orderCreator, address recipient, address tokenIn, address tokenOut, uint256 spendAmount, uint256 yieldSplit, address feeCollector, bool stakeAssetIn, bool stakeAssetOut ) external returns (address vault) ``` Deploys a new vault clone using CREATE2 for deterministic addresses. -------------------------------------------------------------------------------- ## IFillOrderCallback Interface -------------------------------------------------------------------------------- ```solidity interface IFillOrderCallback { function fillOrderCallback( bytes calldata data ) external returns (bool); } ``` Implement this interface for callback-based filling with flash loans or DEX aggregation. -------------------------------------------------------------------------------- ## Events -------------------------------------------------------------------------------- ```solidity event CreateOrder( uint256 indexed orderId, address indexed creator, address recipient, address tokenIn, address tokenOut, uint256 spendAmount, uint256 repeats, uint256 freqInterval, uint256 scalingInterval, uint256 slippage, uint256 firstExecution, bool stakeAssetIn, bool stakeAssetOut ); event FillOrder( uint256 indexed orderId, address caller, address recipient, uint256 fillAmount, uint256 amountOfTokenOut, uint256 protocolFee, uint256 tokenInPrice, uint256 tokenOutPrice ); event CancelOrder( uint256 orderId, address vault ); event SetTokenProps( address indexed token, bytes32 feed, uint8 tokenDecimals, bool isActive, bool isStakable ); ``` -------------------------------------------------------------------------------- ## Error Codes -------------------------------------------------------------------------------- ```solidity // Order Errors error OrderDoesNotExist(); // Invalid order ID error OrderNotActive(); // Order completed or cancelled error NotOrderCreator(); // Only creator can cancel error PriorToOrderExecution(); // Too early to fill // Token Errors error TokenNotActive(); // Token not supported error TokenNotStakable(); // Token cannot be staked error NoFeedIDOnOrder(); // Missing price feed // Parameter Errors error InvalidSlippage(); // Slippage out of bounds (0-2500bp) error InvalidFrequencyInterval(); // Frequency too low (~30s min) error InvalidScalingInterval(); // Scaling interval too high (300s max) error InvalidFirstExecution(); // First execution in past // Execution Errors error InvalidPriceReports(); // Bad oracle data error FeedTooStale(); // Price data too old error TimestampTolerance(); // Feed timestamp mismatch error MinimumExecutionValue(); // Order too small (~$10 min) // Permission Errors error CreateOrderPaused(); // Creation paused error FillOrderPaused(); // Filling paused error Paused(); // Protocol paused ``` ================================================================================ SECTION 3: API REFERENCE ================================================================================ ## Base URL ``` https://api.dca.fun ``` All HTTP endpoints are prefixed with this base URL. WebSocket connects directly. -------------------------------------------------------------------------------- ## GET /quote - Get Fill Quote -------------------------------------------------------------------------------- Returns execution parameters for filling a DCA order with current Chainlink prices. Request: ``` GET https://api.dca.fun/quote?orderId={orderId}&chainId={chainId} ``` Parameters: | Parameter | Type | Required | Description | |-----------|---------|----------|--------------------------| | orderId | integer | Yes | Order ID to quote | | chainId | integer | Yes | Blockchain network ID | Response (Success): ```json { "encodedData": "0x...", "fillableAmount": "100000000", "amountOfTokenOut": "33333333333333333", "scalingFactor": "1000", "tokenInPrice": "1000000000000000000", "tokenOutPrice": "3000000000000000000000" } ``` Response Fields: - encodedData: Hex-encoded data to pass to fillOrder function - fillableAmount: Amount of tokenIn that can be filled (string, BigInt) - amountOfTokenOut: Required output token amount (string, BigInt) - scalingFactor: Current auction scaling factor (string, BigInt) - tokenInPrice: Input token price, 18 decimals (string, BigInt) - tokenOutPrice: Output token price, 18 decimals (string, BigInt) Error Responses: - 400: Missing/invalid parameters - 400: Unconfigured chain - 500: Contract exception (order doesn't exist or inactive) - 502: Oracle error (missing Chainlink price feeds) -------------------------------------------------------------------------------- ## GET /active-orders - Get Fillable Orders -------------------------------------------------------------------------------- Returns all DCA orders currently ready to be filled on a chain. Request: ``` GET https://api.dca.fun/active-orders?chainId={chainId} ``` Parameters: | Parameter | Type | Required | Description | |-----------|---------|----------|-----------------------| | chainId | integer | Yes | Blockchain network ID | Response: ```json { "data": [ { "id": 123, "creator": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "tokenIn": { "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "feed": "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", "decimals": 6, "symbol": "USDC", "name": "USD Coin" }, "tokenOut": { "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "feed": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419", "decimals": 18, "symbol": "WETH", "name": "Wrapped Ether" }, "spendAmount": 100000000, "slippage": 100, "freqInterval": 86400, "lastRun": 1704067200, "nextRun": 1704153600 } ], "count": 1 } ``` Query Logic: Returns orders that meet ALL criteria: - Not cancelled - Current time >= lastRun + freqInterval - Has at least 1 remaining repeat - Sorted by slippage (highest first for filler preference) -------------------------------------------------------------------------------- ## GET /createorder - Get Price Report for Order Creation -------------------------------------------------------------------------------- Fetches the latest Chainlink Data Streams price report for order creation. Request: ``` GET https://api.dca.fun/createorder?tokenFeedId={feedId}&chainId={chainId} ``` Parameters: | Parameter | Type | Required | Description | |-------------|---------|----------|---------------------------------------| | tokenFeedId | string | Yes | Chainlink feed ID (32-byte hex, 0x..) | | chainId | integer | Yes | Blockchain network ID | Response: ```json { "unverifiedReport": ["0x0006f9b553e393ced311551055a5028b580461b2304d48139c8551a749..."], "decodedReport": { "feedId": "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", "validFromTimestamp": 1704067200, "observationsTimestamp": 1704067205, "nativeFee": "1000000000000000", "linkFee": "5000000000000000000", "expiresAt": 1704067500, "price": "3000000000000000000000" } } ``` Usage: Pass unverifiedReport array to createOrder() function as the reports parameter. -------------------------------------------------------------------------------- ## GET /pricetimestamp - Get Historical Price Report -------------------------------------------------------------------------------- Fetches a Chainlink Data Streams price report for a specific timestamp. Request: ``` GET https://api.dca.fun/pricetimestamp?tokenFeedId={feedId}×tamp={timestamp}&chainId={chainId} ``` Parameters: | Parameter | Type | Required | Description | |-------------|---------|----------|------------------------------------------| | tokenFeedId | string | Yes | Chainlink feed ID (hex string) | | timestamp | integer | Yes | Unix timestamp in seconds (10-digit) | | chainId | integer | Yes | Blockchain network ID | -------------------------------------------------------------------------------- ## WebSocket API - Real-time Order Stream -------------------------------------------------------------------------------- Endpoint: ``` wss://api.dca.fun/orders ``` Features: - Updates every 2 seconds - Automatic filtering by chain - Commands: ping, refresh, filter Connection Example: ```javascript const ws = new WebSocket('wss://api.dca.fun/orders'); ws.onopen = () => { // Filter for Base chain orders ws.send(JSON.stringify({ type: 'filter', chainId: 8453 })); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'update') { console.log('Fillable orders:', data.orders); } }; ``` Message Types: - initial: First message with all current orders - update: Periodic updates (every 2 seconds) - refresh: Response to manual refresh command - response: Response to filter/other commands - error: Error messages - pong: Response to ping -------------------------------------------------------------------------------- ## Error Response Format -------------------------------------------------------------------------------- All endpoints use standard HTTP status codes: | Status | Description | |--------|--------------------------------| | 400 | Missing or invalid parameters | | 500 | Server or contract errors | | 502 | External service errors | Error Response: ```json { "error": "Error description message" } ``` ================================================================================ SECTION 4: SCALING FACTOR MECHANISM (DUTCH AUCTION) ================================================================================ ## How It Works DCA.fun uses a linear scaling mechanism to incentivize timely order execution through a Dutch auction. Price Adjustment Formula: ``` adjustedTokenInPrice = tokenInPrice * (BASIS_POINTS + slippage - scalingFactor) / BASIS_POINTS Where: - scalingFactor increases from 0 to (2 * slippage) over scalingInterval - BASIS_POINTS = 10000 ``` Timeline Example (100bp slippage, 120s scaling interval): ``` Time | scalingFactor | User Price | Filler Opportunity --------|---------------|----------------|-------------------- T+0s | 0% | Market + 1% | No profit (worst for filler) T+30s | 25% | Market + 0.5% | 0.5% profit T+60s | 50% | Market | 1% profit (fair execution) T+90s | 75% | Market - 0.5% | 1.5% profit T+120s | 100% | Market - 1% | 2% profit (max for filler) ``` Benefits: 1. Starts expensive for fillers (protects users from MEV) 2. Price gradually improves for fillers over time 3. Competition ensures fills occur near fair market value ================================================================================ SECTION 5: YIELD GENERATION (AAVE INTEGRATION) ================================================================================ When staking is enabled (stakeAssetIn or stakeAssetOut): 1. Tokens are supplied to Aave V3 lending pool 2. Vault receives corresponding aTokens (rebasing tokens) 3. Yield accrues automatically through aToken balance increases 4. Protocol takes configurable percentage (yieldSplit) of earned yield at withdrawal 5. User keeps 100% of principal plus remaining yield Example: ``` Initial Deposit: 1,000 USDC -> 1,000 aUSDC After 6 months: 1,025 aUSDC (2.5% APY) Yield Earned: 25 USDC Protocol Fee (20% of yield): 5 USDC User Receives: 1,020 USDC (principal + 80% of yield) ``` Requirements: - Token must be active Aave V3 reserve - Supply caps are respected - Only charged on actual yield (principal untouched) ================================================================================ SECTION 6: INTEGRATION EXAMPLES ================================================================================ ## Creating an Order (JavaScript) ```javascript import { ethers } from 'ethers'; const DCA_CONTRACT = '0xDCA00000067413240AEaB357a3A89ea352D013E8'; const PERMIT2 = '0x000000000022D473030F116dDEE9F6B43aC78BA3'; async function createDCAOrder( signer, tokenIn, tokenOut, spendAmount, repeats, freqInterval ) { // 1. Fetch price reports for both tokens const tokenInFeed = await getTokenFeed(tokenIn); const tokenOutFeed = await getTokenFeed(tokenOut); const [tokenInReport, tokenOutReport] = await Promise.all([ fetch(`https://api.dca.fun/createorder?tokenFeedId=${tokenInFeed}&chainId=8453`) .then(r => r.json()), fetch(`https://api.dca.fun/createorder?tokenFeedId=${tokenOutFeed}&chainId=8453`) .then(r => r.json()) ]); const unverifiedReports = [ ...tokenInReport.unverifiedReport, ...tokenOutReport.unverifiedReport ]; // 2. Approve Permit2 const tokenContract = new ethers.Contract(tokenIn, ERC20_ABI, signer); const totalAmount = spendAmount * repeats; await tokenContract.approve(PERMIT2, totalAmount); // 3. Prepare order arguments const orderArgs = { recipient: await signer.getAddress(), tokenIn: tokenIn, tokenOut: tokenOut, spendAmount: spendAmount, repeats: repeats, freqInterval: freqInterval, scalingInterval: 300, // 5 minutes max slippage: 100, // 1% firstExecution: 0, // Start after freqInterval stakeAssetIn: false, stakeAssetOut: false }; // 4. Create order const dcaContract = new ethers.Contract(DCA_CONTRACT, DCA_ABI, signer); const tx = await dcaContract.createOrder(orderArgs, unverifiedReports); const receipt = await tx.wait(); // Extract orderId from event const event = receipt.events.find(e => e.event === 'CreateOrder'); return event.args.orderId; } ``` ## Filling an Order (Direct Fill) ```javascript async function fillOrder(signer, orderId, chainId) { // 1. Get quote from API const response = await fetch( `https://api.dca.fun/quote?orderId=${orderId}&chainId=${chainId}` ); const quote = await response.json(); // 2. Calculate profitability const tokenOutDecimals = 18; // Get from order const tokenOutPrice = Number(quote.tokenOutPrice) / 1e18; const outputAmount = Number(quote.amountOfTokenOut) / (10 ** tokenOutDecimals); const outputValueUSD = outputAmount * tokenOutPrice; const tokenInPrice = Number(quote.tokenInPrice) / 1e18; const inputValueUSD = (Number(quote.fillableAmount) / 1e6) * tokenInPrice; // Assuming 6 decimals const profit = inputValueUSD - outputValueUSD; if (profit < 1) { // Minimum $1 profit console.log('Not profitable'); return; } // 3. Ensure Permit2 approval for output token const outputToken = new ethers.Contract(tokenOutAddress, ERC20_ABI, signer); const allowance = await outputToken.allowance(signer.address, PERMIT2); if (allowance.lt(quote.amountOfTokenOut)) { await outputToken.approve(PERMIT2, ethers.constants.MaxUint256); } // 4. Execute fill const dcaContract = new ethers.Contract(DCA_CONTRACT, DCA_ABI, signer); const tx = await dcaContract.fillOrder( quote.encodedData, await signer.getAddress() ); return tx.wait(); } ``` ## Callback Fill (Flash Loan Strategy) ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {IFillOrderCallback} from "./interfaces/IFillOrderCallback.sol"; import {IDcaDotFun} from "./interfaces/IDcaDotFun.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract FlashFillRouter is IFillOrderCallback { // Transient storage for reentrancy protection bytes32 internal constant LOCKED_SLOT = 0xab99c6d7581cbb37d2e578d3097bfdd3323e05447f1fd7670b6c3a3fb9d9ff79; address public immutable dcaDotFun; address public immutable permit2; constructor(address _dcaDotFun, address _permit2) { dcaDotFun = _dcaDotFun; permit2 = _permit2; } modifier onlyWhenUnlocked() { require(isUnlocked(), "Not unlocked"); _; } function unlock() internal { assembly { tstore(LOCKED_SLOT, true) } } function lock() internal { assembly { tstore(LOCKED_SLOT, false) } } function isUnlocked() internal view returns (bool unlocked) { assembly { unlocked := tload(LOCKED_SLOT) } } function executeSwap( bytes calldata encodedData, bytes calldata swapData ) external { unlock(); IDcaDotFun(dcaDotFun).fillOrder( encodedData, address(this), // callback address(this), // initiator address(this) // recipient ); lock(); } function fillOrderCallback( bytes calldata data ) external onlyWhenUnlocked returns (bool) { // 1. Decode swap parameters (address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut, bytes memory swapData) = abi.decode(data, (address, address, uint256, uint256, bytes)); // 2. Execute DEX swap with received tokenIn // ... custom swap logic here ... // 3. Approve output token to Permit2 IERC20(tokenOut).approve(permit2, amountOut); return true; } } ``` ## Monitoring Orders (WebSocket) ```javascript class OrderMonitor { constructor(chainId) { this.chainId = chainId; this.orders = new Map(); this.ws = null; } connect() { this.ws = new WebSocket('wss://api.dca.fun/orders'); this.ws.onopen = () => { console.log('Connected to order stream'); this.ws.send(JSON.stringify({ type: 'filter', chainId: this.chainId })); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'initial' || message.type === 'update') { this.processOrders(message.data); } }; this.ws.onclose = () => { console.log('Disconnected, reconnecting in 5s...'); setTimeout(() => this.connect(), 5000); }; this.ws.onerror = (error) => { console.error('WebSocket error:', error); }; } processOrders(orders) { const currentIds = new Set(); for (const order of orders) { currentIds.add(order.id); if (!this.orders.has(order.id)) { console.log(`New fillable order: ${order.id}`); this.onNewOrder(order); } this.orders.set(order.id, order); } // Remove filled/cancelled orders for (const [id] of this.orders) { if (!currentIds.has(id)) { console.log(`Order ${id} no longer fillable`); this.orders.delete(id); } } } async onNewOrder(order) { // Evaluate and potentially fill the order try { const quote = await fetch( `https://api.dca.fun/quote?orderId=${order.id}&chainId=${this.chainId}` ).then(r => r.json()); // Calculate profitability and decide whether to fill // ... } catch (error) { console.error(`Error processing order ${order.id}:`, error); } } } ``` ================================================================================ SECTION 7: PROTOCOL PARAMETERS ================================================================================ | Parameter | Description | Typical Value | Constraints | |---------------------|--------------------------------|------------------|------------------------| | protocolFee | Fee on output tokens | 0.5% (50 bp) | Max 50 bp | | minExecutionValue | Minimum order USD value | ~$10 | Per iteration | | maxFeedAge | Price data staleness limit | 5 seconds | Configurable | | minFrequency | Minimum time between fills | ~30 seconds | Protocol minimum | | maxScalingInterval | Maximum Dutch auction duration | 300 seconds | Protocol maximum | | maxSlippage | Maximum allowed slippage | 25% (2500 bp) | Per order | | yieldSplit | Protocol share of yield | 20% (2000 bp) | Configurable | ================================================================================ SECTION 8: SECURITY CONSIDERATIONS ================================================================================ ## Access Control Roles - DEFAULT_ADMIN_ROLE: Full protocol control, configuration - PAUSER_ROLE: Can pause create/fill operations independently - Order Creator: Can cancel own orders only - Order Recipient: Can withdraw from their vault ## Security Features 1. Reentrancy Protection: All external functions use nonReentrant modifier 2. Vault Isolation: Each order has separate vault contract 3. Pause Mechanism: Create and fill can be paused independently 4. Price Feed Validation: Chainlink signatures verified on-chain 5. Freshness Checks: Price data age enforced 6. Timestamp Tolerance: Feed timestamp mismatch detection ## Callback Security Warning When implementing IFillOrderCallback: - Use transient storage lock pattern to prevent unauthorized callbacks - Reset token allowances to 0 after each fill - Use exact approval amounts rather than max approvals - Implement access controls on callback function - Audit thoroughly before production use ## Permit2 Considerations - Fillers must approve Permit2 contract: 0x000000000022D473030F116dDEE9F6B43aC78BA3 - Router contracts with persistent Permit2 allowances are vulnerable - Consider using separate routers per token pair ================================================================================ SECTION 9: GAS OPTIMIZATION ================================================================================ Estimated Gas Costs: | Operation | Gas Cost | |--------------|------------| | Create Order | ~300,000 | | Fill Order | ~150,000 | | Cancel Order | ~100,000 | Optimization Techniques Used: 1. Clone Pattern: Vaults deployed as minimal proxies (~95% gas savings) 2. Packed Storage: Order struct optimized for efficient storage 3. Immutable Variables: Common addresses stored in bytecode 4. Batch Operations: Cancel multiple orders in single tx 5. CREATE2: Predictable vault addresses ================================================================================ SECTION 10: RESOURCES ================================================================================ ## Official Links - Documentation: https://docs.dca.fun - GitHub (Contracts): https://github.com/DCADOTFUN/dcaDotFun-contracts - GitHub (Audits): https://github.com/DCADOTFUN/audits - API Base URL: https://api.dca.fun - WebSocket: wss://api.dca.fun/orders ## Key Addresses - Permit2: 0x000000000022D473030F116dDEE9F6B43aC78BA3 (universal) - DcaDotFun: 0xDCA00000067413240AEaB357a3A89ea352D013E8 (Base & Base Sepolia) - DcaVaultFactory: 0xFAC000000118455B405Fb8eda255E08315eF0E4f (Base & Base Sepolia) - VerifierDotFun: 0x0000000004708392169a21A550a7Dc89A777C9cc (Base & Base Sepolia) ## Audits Security audits performed by Nethermind. Reports available at: https://github.com/DCADOTFUN/audits ================================================================================ END OF DOCUMENT ================================================================================ # Metadata for LLM Consumption # Protocol: DCA.fun # Type: DeFi Dollar Cost Averaging # Networks: EVM-compatible (Base, Base Sepolia) # Key Features: Isolated vaults, Aave yield, Chainlink oracles, Dutch auction # Integration Complexity: Medium # Last Verified: 2026-01-07