Dollar-Cost Averaging (DCA)

The goal of this task is to periodically buy a fixed amount of a token using slippage-protected swaps.

For example, suppose the inputs are:

  • Token In: USDC

  • Token Out: WETH

And the cron trigger schedule is 30 19 * * 0, meaning:

  • 30 -> minute

  • 19 -> hour UTC

  • * -> every day of the month

  • * -> every month

  • 0 -> 0 = Sunday, 1 = Monday, etc

Then the task will buy 100 USDC worth of WETH every Sunday at 7:30 PM UTC.

Task

import { BigInt, ERC20Token, log, SwapBuilder, TokenAmount } from '@mimicprotocol/lib-ts'

import { inputs } from './types'

const BPS_DENOMINATOR = BigInt.fromI32(10_000)

export default function main(): void {
  // Log input parameters
  log.info(
    `Starting DCA swap: amountFromToken=${inputs.amount}, slippageBps=${inputs.slippageBps}, chainId=${inputs.chainId}, recipient=${inputs.recipient}`
  )

  // Create token instances
  const tokenIn = ERC20Token.fromAddress(inputs.tokenIn, inputs.chainId)
  const tokenOut = ERC20Token.fromAddress(inputs.tokenOut, inputs.chainId)

  // Create amount from decimal string and estimate amount out
  const amountIn = TokenAmount.fromStringDecimal(tokenIn, inputs.amount)
  const expectedOut = amountIn.toTokenAmount(tokenOut)

  // Apply slippage to calculate the expected minimum amount out
  const slippageFactor = BPS_DENOMINATOR.minus(BigInt.fromI32(inputs.slippageBps as i32))
  const minAmountOut = expectedOut.times(slippageFactor).div(BPS_DENOMINATOR)
  log.info(`Calculated minOut: ${minAmountOut} (equivalent=${expectedOut}, slippageBps=${inputs.slippageBps})`)

  // Create and execute swap
  SwapBuilder.forChain(inputs.chainId)
    .addTokenInFromTokenAmount(amountIn)
    .addTokenOutFromTokenAmount(minAmountOut, inputs.recipient)
    .build()
    .send()

  log.info('DCA swap executed successfully')
}

Manifest

version: 1.0.0
name: DCA
description: Dollar-cost averaging task that swaps tokenIn to tokenOut
inputs:
  - chainId: uint32
  - tokenIn: address
  - tokenOut: address
  - amount: string        # e.g., '1.5' = 1.5 tokenIn
  - slippageBps: uint16   # e.g., 50 = 0.50%
  - recipient: address

Last updated