Quick Start
From zero to your first DomFi contract interaction in under 10 minutes. Read prices, open trades, and deposit into the vault.
Prerequisites
- JavaScript path: Node.js 18+
- Solidity / CLI path: Foundry (includes
forge,cast, andanvil) - A wallet with ETH on Base for gas and oracle fees
- USDC on Base for collateral
- An RPC endpoint for Base:
https://mainnet.base.orgfor public access, or Alchemy/Infura for production
Install
npm install viemnpm install etherscurl -L https://foundry.paradigm.xyz | bash
foundryupIncludes forge (build/test/script), cast (CLI calls), and anvil (local node). No Node.js required.
Connect to the Protocol
Start from the deployed Base mainnet addresses below. DomfiRegistry is the discovery entry point, but most integrations pin the current proxy addresses directly.
| Contract | Address | Use For |
|---|---|---|
| DomfiRegistry | 0xe438360464EaDa40b7921C993322bD4dA8881103 | Discover all other contracts |
| DomfiTrading | 0x7447cb5350a096364A13bEAf77916dfB35db9445 | Open and close trades |
| DomfiOracle | 0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D | Read dominance prices |
| DomfiVault | 0xA194082Aabb75Dd1Ca9Dc1BA573A5528BeB8c2Fb | LP deposits and withdrawals |
| DomfiTradingStorage | 0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24 | Query open positions |
import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';
const client = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});Or verify your connection with cast (included with Foundry):
cast chain-id --rpc-url https://mainnet.base.org
# Expected: 8453Use minimal ABI fragments for the specific calls you make. For full verified ABIs, use BaseScan:
Read a Dominance Price
const price = await client.readContract({
address: '0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D',
abi: [{
name: 'getPrice',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'pairIndex', type: 'uint16' }],
outputs: [{ name: '', type: 'uint256' }],
}],
functionName: 'getPrice',
args: [0], // 0 = BTCDOM
});
console.log('BTCDOM price:', Number(price) / 1e18);
// Expected: ~52.5 (Bitcoin dominance percentage)import { Contract, JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://mainnet.base.org');
const oracle = new Contract(
'0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D',
[{
name: 'getPrice',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'pairIndex', type: 'uint16' }],
outputs: [{ name: '', type: 'uint256' }],
}],
provider,
);
const price = await oracle.getPrice(0);
console.log('BTCDOM price:', Number(price) / 1e18);
// Expected: ~52.5 (Bitcoin dominance percentage)// ReadPrice.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
interface IDomfiOracle {
function getPrice(uint16 pairIndex) external view returns (uint256);
}
contract ReadPrice is Script {
function run() external view {
IDomfiOracle oracle = IDomfiOracle(
0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D
);
uint256 price = oracle.getPrice(0); // 0 = BTCDOM
console.log("BTCDOM price (18 decimals):", price);
// Expected: ~52500000000000000000 (52.5%)
}
}forge script ReadPrice.s.sol --rpc-url https://mainnet.base.orgNo setup required — read a price in one command:
cast call 0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D \
"getPrice(uint16)(uint256)" \
0 \
--rpc-url https://mainnet.base.org
# Returns: 52500000000000000000 (18 decimals → 52.5% BTCDOM)| Index | Pair |
|---|---|
| 0 | BTCDOM |
| 1 | ETHDOM |
| 2 | USDTDOM |
| 3 | BNBDOM |
| 4 | SOLDOM |
Open a Trade (Write)
openTrade() submits a real on-chain order. Approve USDC to DomfiTradingStorage, not DomfiTrading, then wait for the approval receipt before you submit the trade. Both steps spend real gas, and openTrade() also requires an ETH oracle fee.
Before you send the transaction:
- USDC must be approved to DomfiTradingStorage, not
DomfiTrading. This is the most common integration mistake. openTrade()requires ETH asmsg.valuefor the oracle fee, typically around0.00003 ETH.- Collateral uses 6 decimals because USDC on Base is 6-decimal native USDC.
- Leverage uses 2-decimal precision:
100= 1x,1000= 10x,5000= 50x,25000= 250x. - Execution is asynchronous.
openTrade()queues the order, then an off-chain bot fulfills the price.
import { createPublicClient, createWalletClient, http, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const TRADING_ADDRESS = '0x7447cb5350a096364A13bEAf77916dfB35db9445';
const TRADING_STORAGE_ADDRESS = '0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24';
const ORACLE_FEE_WEI = 30000000000000n;
const erc20Abi = [{
name: 'approve',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ name: '', type: 'bool' }],
}] as const;
const tradingAbi = [{
name: 'openTrade',
type: 'function',
stateMutability: 'payable',
inputs: [
{
name: 't',
type: 'tuple',
components: [
{ name: 'collateral', type: 'uint256' },
{ name: 'openPrice', type: 'uint192' },
{ name: 'tp', type: 'uint192' },
{ name: 'sl', type: 'uint192' },
{ name: 'trader', type: 'address' },
{ name: 'leverage', type: 'uint32' },
{ name: 'pairIndex', type: 'uint16' },
{ name: 'index', type: 'uint8' },
{ name: 'buy', type: 'bool' },
],
},
{ name: 'orderType', type: 'uint8' },
{ name: 'slippageP', type: 'uint256' },
],
outputs: [],
}] as const;
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const publicClient = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});
const walletClient = createWalletClient({
account,
chain: base,
transport: http('https://mainnet.base.org'),
});
// Step 1: Approve USDC to TradingStorage (not Trading)
const approvalHash = await walletClient.writeContract({
address: USDC_ADDRESS,
abi: erc20Abi,
functionName: 'approve',
args: [TRADING_STORAGE_ADDRESS, parseUnits('100', 6)],
});
await publicClient.waitForTransactionReceipt({ hash: approvalHash });
// Step 2: Submit a 10x long on BTCDOM
await walletClient.writeContract({
address: TRADING_ADDRESS,
abi: tradingAbi,
functionName: 'openTrade',
args: [
{
trader: account.address,
pairIndex: 0,
index: 0,
collateral: parseUnits('100', 6),
openPrice: 0n,
buy: true,
leverage: 1000,
tp: 0n,
sl: 0n,
},
0,
50,
],
value: ORACLE_FEE_WEI,
});// OpenTrade.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script} from "forge-std/Script.sol";
interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
}
interface IDomfiTrading {
struct Trade {
uint256 collateral;
uint192 openPrice;
uint192 tp;
uint192 sl;
address trader;
uint32 leverage;
uint16 pairIndex;
uint8 index;
bool buy;
}
function openTrade(Trade calldata t, uint8 orderType, uint256 slippageP) external payable;
}
contract OpenTrade is Script {
address constant USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address constant TRADING = 0x7447cb5350a096364A13bEAf77916dfB35db9445;
address constant TRADING_STORAGE = 0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24;
function run() external {
vm.startBroadcast();
// Step 1: Approve USDC to TradingStorage (not Trading)
IERC20(USDC).approve(TRADING_STORAGE, 100e6); // 100 USDC
// Step 2: Submit a 10x long on BTCDOM
IDomfiTrading(TRADING).openTrade{value: 0.00003 ether}(
IDomfiTrading.Trade({
collateral: 100e6, // 100 USDC (6 decimals)
openPrice: 0, // market order — filled by oracle
tp: 0, // no take profit
sl: 0, // no stop loss
trader: msg.sender,
leverage: 1000, // 10x (2 decimal precision)
pairIndex: 0, // BTCDOM
index: 0, // first trade slot
buy: true // long
}),
0, // 0 = market order
50 // 0.5% slippage (2 decimals)
);
vm.stopBroadcast();
}
}forge script OpenTrade.s.sol \
--rpc-url https://mainnet.base.org \
--private-key 0xYOUR_PRIVATE_KEY \
--broadcastThe order is not opened immediately. Wait for the price bot to fulfill it, then read the resulting position from DomfiTradingStorage or watch the MarketOpenExecuted event.
Decimal Reference
| Value | Precision | Example |
|---|---|---|
| USDC amounts (collateral) | 6 decimals | $100 = 100000000 |
| Prices (dominance) | 18 decimals | 52.5% = 52500000000000000000 |
| Leverage | 2 decimals | 10x = 1000, 250x = 25000 |
| Slippage | 2 decimals | 0.5% = 50 |
| Fee rates | 2 decimals | 0.1% = 10 |