Status: Reference implementation / draft: the standard and interface are still open for feedback. Please open an issue (or PR) with suggestions, edge-cases, or compatibility concerns.
A minimal ERC20-like fungible token reference implementation for the DuskDS network.
contract/— the on-chain DRC20 contract (WASM)types/— shared types (accounts, call args, events, error strings)web/— minimal admin/management UI (connect + read + send tx)
name() -> Stringsymbol() -> Stringdecimals() -> u8total_supply() -> u64balance_of(BalanceOf) -> u64allowance(Allowance) -> u64
transfer(TransferCall)approve(ApproveCall)transfer_from(TransferFromCall)
transfer(events::Transfer)approval(events::Approval)
- Rust toolchain pinned in
rust-toolchain.toml - wasm target:
rustup target add wasm32-unknown-unknown
jqis used by Makefiles (cargo metadataparsing).- Optional:
wasm-opt(from Binaryen) for optimized outputs.
make wasm-opt
# output: target/wasm32-unknown-unknown/release/drc20_opt.wasmThe data-driver is auto-generated from the contract via Dusk Forge (no separate
data-driver/ crate) and can be used by any runtime that supports WASM.
make data-driver
# output: target/data-driver/wasm32-unknown-unknown/release/drc20_opt.wasmThis command also copies the WASM into web/public/data_driver.wasm.
cd web
npm i
npm run devOpen:
http://localhost:5173/?network=testnet&contractId=0xYOUR_32B_CONTRACT_ID
Optional overrides:
&nodeUrl=https://testnet.nodes.dusk.network&driverUrl=/data_driver.wasm
This repo expects an init.json in the repo root describing the initial distribution.
init.jsonis git-ignored (so you can safely keep local addresses / configs out of version control).example.init.jsonis committed as a starting point.
Create your local init.json:
cp example.init.json init.json
# edit init.jsonExample format:
{
"initial_balances": [
{ "account": { "External": "26brdzqNXEG1jTzCubJAPhks18bSSDY4n21ZW6VLYkCv6bBUdBAZZAbn1Coz1LPBYc4uEekBbzFnZvhL9untGCqRamhZS2cBV51fdZog3qkP3NbMEaqgNMcKEahAFV8t2Cke" }, "amount": "1000" }
]
}Notes:
Externalis a public account (base58).- Amounts are
u64and accepted as JSON strings (to avoid JS precision issues).
Generate the rkyv-encoded hex string expected by most deploy tooling:
make init-args FILE=./init.json
# prints: <hex>Note:
make init-argsdefaults to./init.jsonif you don't passFILE=....
Deploy using your preferred tooling (e.g. rusk-wallet contract-deploy).
Deploy tooling must pass constructor args. To deploy with zero supply, use an
empty initial_balances list in Init.
The repo includes a small spec test-suite that runs the contract in dusk-vm and
asserts the classic ERC20 behaviors (balances, allowances, events, failure cases).
It also deploys a tiny helper contract to prove the "contract caller" path works
(i.e. sender_account() resolves to Account::Contract(...) for ICC calls).
Run the tests:
make testThis will:
- Build
contract/totarget/wasm32-unknown-unknown/release/drc20.wasm - Build the helper contract to
target/wasm32-unknown-unknown/release/drc20_test_caller.wasm - Run
cargo test -p drc20-tests
init(Init)is intended to be called at deployment with an initial distribution.- The contract is transparent only (requires a public sender, shielded tx not supported).
ZERO_ADDRESSis reserved for mint events (from = ZERO_ADDRESS).
MIT © Dusk Forge.