Vordium LabsDocs

Your first contract

A Solidity contract that places orders on VordCore through CoreWriter — compile it, check every call against the testnet, then deploy it.

Testnet only · contracts run on the testnet

A contract on the EVM lane can trade on VordCore through CoreWriter. The contract has its own account on the core: it trades with the USDC that account holds, and every order it places is an ordinary order on the book.

The contract

LimitBot.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface ICoreWriter {
    function sendRawAction(bytes calldata data) external;
}

/// Places limit orders on VordCore for this contract's own account.
contract LimitBot {
    ICoreWriter constant CORE_WRITER = ICoreWriter(0x7777777777777777777777777777777777777777);
    address public immutable owner;

    constructor() {
        owner = msg.sender;
    }

    /// Move USDC this contract holds on the EVM lane to its account on the core (action 4).
    function fund(uint64 usdc6) external {
        require(msg.sender == owner, "not the owner");
        CORE_WRITER.sendRawAction(abi.encodePacked(uint8(2), uint24(4), abi.encode(usdc6)));
    }

    /// Place a limit order (action 10). Price and size carry 8 decimals.
    function placeLimit(uint32 pair, bool isBuy, uint64 limitPx, uint64 size, uint8 tif, uint128 cloid) external {
        require(msg.sender == owner, "not the owner");
        CORE_WRITER.sendRawAction(abi.encodePacked(uint8(2), uint24(10), abi.encode(pair, isBuy, limitPx, size, false, tif, cloid)));
    }

    /// Cancel it by your own id (action 12).
    function cancel(uint32 pair, uint128 cloid) external {
        require(msg.sender == owner, "not the owner");
        CORE_WRITER.sendRawAction(abi.encodePacked(uint8(2), uint24(12), abi.encode(pair, cloid)));
    }
}

Compile it and check it against the testnet

This compiles the contract, asks the testnet what deploying it would cost, and simulates the CoreWriter call its placeLimit makes. Nothing is sent and no funded key is needed.

Python
# needs solc 0.8.19 or later:  pip install vordium==1.4.6 requests
import subprocess, requests
from eth_abi import encode
from eth_utils import keccak

EVM = "https://rpc-testnet.vordium.com/evmrpc"
def rpc(method, params):
    return requests.post(EVM, json={"jsonrpc": "2.0", "id": 1, "method": method, "params": params}, timeout=15).json()

out = subprocess.run(["solc", "--bin", "--optimize", "LimitBot.sol"], capture_output=True, text=True, check=True).stdout
bytecode = "0x" + out.strip().splitlines()[-1]
me = "0x000000000000000000000000000000000000dEaD"
print("deploy gas:", int(rpc("eth_estimateGas", [{"from": me, "data": bytecode}])["result"], 16))

# the call placeLimit(1, true, 2000 USDC, 0.01 ETH, post only, 42) makes to CoreWriter
action = b"\x02" + (10).to_bytes(3, "big") + encode(
    ["uint32", "bool", "uint64", "uint64", "bool", "uint8", "uint128"], [1, True, 2_000 * 10**8, 10**6, False, 1, 42])
call = {"from": me, "to": "0x7777777777777777777777777777777777777777",
        "data": "0x" + keccak(b"sendRawAction(bytes)")[:4].hex() + encode(["bytes"], [action]).hex()}
print("placeLimit accepted:", "result" in rpc("eth_call", [call, "latest"]))

Deploy it

Deploy it with any Ethereum tool pointed at the testnet's EVM lane, https://rpc-testnet.vordium.com/evmrpc — for example with ethers.js, from the compiled bytecode:

TypeScript
import { JsonRpcProvider, Wallet, ContractFactory } from 'ethers'
const wallet = new Wallet(process.env.PRIVATE_KEY!, new JsonRpcProvider('https://rpc-testnet.vordium.com/evmrpc'))
const factory = new ContractFactory(abi, bytecode, wallet)      // abi and bytecode from solc --abi --bin
const bot = await factory.deploy()
console.log('LimitBot at', await bot.getAddress())

Deploying and calling need test VORD for gas on the EVM lane.

Fund it and trade

  1. Send the contract USDC on the EVM lane (the ERC-20 at 0x2000000000000000000000000000000000000000).
  2. Call fund(amount) to move it to the contract's account on the core.
  3. Call placeLimit(...). The order reaches the book at least three seconds later; find it with GET /orders/{contract address} on the REST API.
  4. Call cancel(pair, cloid) to take it off.

Network facts last checked against the network 2026-10-22 13:00:37 UTC · mainnet spec v28 · testnet spec v8

On this page