Smart Contracts
Technical reference for DCA.fun smart contracts
Smart Contracts
Complete reference for all DCA.fun protocol contracts.
Core Contracts
DcaDotFun.sol
Main protocol contract managing orders:
contract DcaDotFun is DotFun, IDcaDotFun, ReentrancyGuard {
// Order Management
function createOrder(OrderArgs calldata args, bytes[] calldata reports) external;
function cancelOrders(uint256[] calldata orderIds) external;
function fillOrder(bytes calldata data, address recipient) external;
// Queries
function getOrders(uint256[] calldata ids) external view returns (Order[] memory);
function quote(uint256 id, bytes[] calldata reports) external returns (bytes memory, OrderValidation memory);
function getOrderTokens(uint256[] calldata ids) external view returns (OrderTokens[] memory);
}Key Functions
createOrder
function createOrder(
OrderArgs calldata args,
bytes[] calldata reports
) external returns (uint256 orderId)Creates a new DCA order with the specified parameters.
Parameters:
args: Order configuration (see OrderArgs struct below)reports: Chainlink price reports for token validation
fillOrder
function fillOrder(
bytes calldata data,
address recipient
) externalExecutes an order fill using encoded quote data.
Parameters:
data: Encoded quote data from the APIrecipient: Address to receive profit
DcaVault.sol
Isolated vault for each order:
contract DcaVault is Initializable, Ownable, IDcaVault {
// State variables
uint256 public orderId;
uint256 public yieldSplit;
uint256 public escrow;
uint256 public totalFills;
uint256 public spendAmount;
address public funContract;
address public feeCollector;
address public recipient;
address public tokenIn;
address public aTokenIn;
address public tokenOut;
address public aTokenOut;
address public pool;
bool public isCancelled;
// Protocol Functions
function fillOrder(address recipient, uint256 amount, uint256 escrow) external;
function cancelOrder(uint256 repeats) external;
// Owner Functions
function withdrawErc20(address token) external;
function withdrawNative() external;
}DcaVaultFactory.sol
Deploys vault clones:
contract DcaVaultFactory {
address public implementation;
address public aavePool;
mapping(uint256 => address) public vaults;
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);
}Data Structures
OrderArgs Struct
struct OrderArgs {
address recipient; // Who receives output tokens
address tokenIn; // Input token address
address tokenOut; // Output token address
uint256 spendAmount; // Amount per execution
uint256 repeats; // Number of executions
uint256 freqInterval; // Time between executions
uint256 scalingInterval; // Dutch auction duration
uint256 slippage; // Max price deviation (basis points)
uint256 firstExecution; // Delay before first execution
bool stakeAssetIn; // Stake input in Aave
bool stakeAssetOut; // Stake output in Aave
}Order Struct
struct Order {
address creator; // Order creator
uint16 slippage; // Slippage tolerance
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 time
uint256 protocolFee; // Fee at creation
address vault; // Vault address
}OrderValidation Struct
struct OrderValidation {
uint256 scalingFactor;
uint256 effectiveSlippage;
uint256 fillableAmount;
uint256 amountOfTokenOut;
uint256 inAmount;
uint256 minOutAmount;
bool valid;
}Key Interfaces
IFillOrderCallback
For advanced filling strategies:
interface IFillOrderCallback {
function fillOrderCallback(
address tokenOut,
uint256 amountOfTokenOut,
address initiator
) external returns (bool);
}IDcaDotFun
Main protocol interface:
interface IDcaDotFun {
// Order creation
function createOrder(OrderArgs calldata args, bytes[] calldata reports) external;
function createOrderNative(OrderArgs calldata args, bytes[] calldata reports) external payable;
// Order management
function cancelOrders(uint256[] calldata orderIds) external;
// Order execution
function fillOrder(bytes calldata data, address recipient) external;
function fillOrder(bytes calldata data, address callback, address initiator, address recipient) external;
// Queries
function getOrders(uint256[] calldata ids) external view returns (Order[] memory);
function quote(uint256 id, bytes[] calldata reports) external returns (bytes memory, OrderValidation memory);
function getOrderTokens(uint256[] calldata ids) external view returns (OrderTokens[] memory);
// Token management
function getTokenProps(address token) external view returns (TokenProps memory);
function setTokenProps(address token, bytes32 priceFeed, bool isStakable) external;
}Events
Monitor protocol activity with these events:
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
Common errors and their meanings:
// 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 can't be staked
error No FeedID on Order(); // Missing price feed
// Parameter Errors
error InvalidSlippage(); // Slippage out of bounds
error InvalidFrequencyInterval(); // Frequency too low
error InvalidScalingInterval(); // Scaling interval too high
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
// Permission Errors
error CreateOrderPaused(); // Creation paused
error FillOrderPaused(); // Filling paused
error Paused(); // Protocol pausedContract Addresses
Base Mainnet
| Contract | Address |
|---|---|
| DcaDotFun | Coming Soon |
| DcaVaultFactory | Coming Soon |
| VerifierDotFun | Coming Soon |
Base Sepolia
| Contract | Address |
|---|---|
| DcaDotFun | 0x41177B8b91F59e29B088d78a9D7DdD8ce99E8998 |
| DcaVaultFactory | TBD |
| VerifierDotFun | TBD |
Monad Testnet
| Contract | Address |
|---|---|
| DcaDotFun | 0xB2D1FA47E6F4Cb3c973f06EA2130078BD4D63c39 |
| DcaVaultFactory | TBD |
| VerifierDotFun | TBD |
Security Features
Access Control
DEFAULT_ADMIN_ROLE: Full protocol controlPAUSER_ROLE: Emergency pause functions- Order creators can only cancel their own orders
- Vaults are owned by order creators
Reentrancy Protection
All external functions that transfer tokens use reentrancy guards:
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(localCounter == _guardCounter);
}Price Feed Validation
- Chainlink Data Streams verification
- Freshness checks on price data
- Tolerance limits for feed timestamps
Pause Mechanism
modifier whenOrderCreateNotPaused() {
if (isCreateOrderPaused) revert CreateOrderPaused();
_;
}
modifier whenOrderFillNotPaused() {
if (isFillOrderPaused) revert FillOrderPaused();
_;
}Integration Examples
Creating an Order
// 1. Approve tokens
IERC20(tokenIn).approve(dcaDotFun, totalAmount);
// 2. Prepare order arguments
OrderArgs memory args = OrderArgs({
recipient: msg.sender,
tokenIn: USDC,
tokenOut: WETH,
spendAmount: 100e6, // 100 USDC
repeats: 52, // Weekly for a year
freqInterval: 7 days,
scalingInterval: 1 days,
slippage: 100, // 1%
firstExecution: 0,
stakeAssetIn: true,
stakeAssetOut: false
});
// 3. Create order
uint256 orderId = dcaDotFun.createOrder(args, priceReports);Filling an Order
// 1. Get quote from API
bytes memory encodedData = getQuoteFromAPI(orderId);
// 2. Fill order
dcaDotFun.fillOrder(encodedData, msg.sender);Using Callbacks
contract MyFiller is IFillOrderCallback {
function fillWithCallback(bytes calldata encodedData) external {
dcaDotFun.fillOrder(
encodedData,
address(this), // callback
msg.sender, // initiator
msg.sender // recipient
);
}
function fillOrderCallback(
address tokenOut,
uint256 amountOfTokenOut,
address initiator
) external returns (bool) {
// Custom logic here
// 1. Receive tokenIn from protocol
// 2. Execute swap on DEX
// 3. Approve tokenOut to protocol
return true;
}
}Gas Optimization
The protocol uses several techniques to minimize gas costs:
- Clone Pattern: Vaults deployed as minimal proxies
- Packed Storage: Order struct optimized for storage
- Immutable Variables: Common addresses in bytecode
- Batch Operations: Cancel multiple orders at once
Gas Costs (Estimated)
| Operation | Gas Cost |
|---|---|
| Create Order | ~300,000 |
| Fill Order | ~150,000 |
| Cancel Order | ~100,000 |
Audits
- Audit Report #1:
Coming Soon - Audit Report #2:
Coming Soon
Source Code
The complete DCA.fun smart contract source code is publicly available on GitHub:
🔗 github.com/DCADOTFUN/dcaDotFun-contracts
The repository includes:
- Complete Solidity source code for all contracts
- Comprehensive test suite with Foundry
- Deployment scripts and configurations
- Development environment setup
- API documentation and examples
You can also view verified contracts on block explorers: