Automated DCA into any OP20 token, powered by OPNet smart contracts on Bitcoin.
BitDCA lets users deposit tokens and configure recurring swaps via MotoSwap. A keeper bot monitors positions and triggers executions at configured intervals, delivering purchased tokens directly to the user's wallet.
bitdca/
├── contracts/ AssemblyScript smart contract (DCAVault)
├── frontend/ React + Vite dashboard
└── keeper/ Node.js keeper bot
- DCAVault — On-chain position management with reentrancy protection
- Users deposit OP20 tokens and set amount, interval, and target token
- Keeper-triggered swaps via MotoSwap router with slippage protection
- Position top-up, cancellation with refund, auto-deactivation when exhausted
- Uses
TransferHelper/OP20Utilsfrom btc-runtime for correct SHA256 selectors - Emergency pause by deployer
- React 19 + TypeScript + Vite + TailwindCSS
@btc-vision/walletconnectfor native OPNet wallet integration- Real-time position monitoring with block countdown timers
- Create, top-up, and cancel positions
- Uses
increaseAllowance(notapprove) per OP20 ATK-05
- Polls all active positions every 30s
- Fetches MotoSwap quotes for slippage calculation
- Simulates then sends execution transactions
- Configurable via environment variables
- Node.js 18+
- An OPNet wallet (e.g., OPWallet browser extension)
# Install all dependencies
cd contracts && npm install && cd ..
cd frontend && npm install && cd ..
cd keeper && npm install && cd ..
# Build the smart contract (WASM)
cd contracts && npm run build
# Build the frontend
cd frontend && npm run build
# Build the keeper
cd keeper && npm run buildcd frontend
npm run devcd keeper
DCA_VAULT_ADDRESS=0x... KEEPER_MNEMONIC="your words here" npm start| Variable | Default | Description |
|---|---|---|
RPC_URL |
https://testnet.opnet.org |
OPNet RPC endpoint |
NETWORK |
testnet |
Network: regtest, testnet, mainnet |
DCA_VAULT_ADDRESS |
— | Deployed DCAVault hex address |
ROUTER_ADDRESS |
MotoSwap regtest | MotoSwap router hex address |
KEEPER_MNEMONIC |
dev mnemonic | BIP39 mnemonic for keeper wallet |
POLL_INTERVAL_MS |
30000 |
How often to scan positions |
SLIPPAGE_PERCENT |
5 |
Max slippage tolerance |
MAX_SATS_PER_TX |
50000 |
Max sats per execution TX |
FEE_RATE |
10 |
Fee rate (sat/vB) |
Deploy with the OPNet CLI:
cd contracts
npx opnet-cli deploy --wasm build/dca.wasm \
--abi abis/DCAVault.abi.json \
--args ROUTER_ADDRESS,KEEPER_ADDRESSAfter deployment, update DCA_VAULT_ADDRESS in:
frontend/src/config/contracts.ts- Keeper's environment variable
-
SHA256 selectors — OPNet uses SHA256 (not keccak256) for function selectors. All cross-contract calls use
encodeSelector()from btc-runtime. -
increaseAllowanceoverapprove— Prevents the ERC20 approval race condition (ATK-05). -
Balance-diff pattern for swaps — MotoSwap's
swapExactTokensForTokensSupportingFeeOnTransferTokensreturns void, so we snapshot balances before/after to measure output. -
Reentrancy guard — DCAVault extends
ReentrancyGuardwithSTANDARDlevel protection. -
State-before-interaction — All state updates happen before external calls (CEI pattern).
- Smart Contract: AssemblyScript +
@btc-vision/btc-runtime - Frontend: React 19 + Vite + TailwindCSS +
@btc-vision/walletconnect - Keeper: Node.js + TypeScript +
opnetSDK - DEX: MotoSwap (on-chain AMM)
- Network: OPNet (Bitcoin L1 smart contracts)
MIT