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 ERC721-like non-fungible token reference implementation for the DuskDS network.
contract/— the on-chain DRC721 contract (WASM)types/— shared types (accounts, call args, events, error strings)tools/— helper CLI tooling (constructor args)tests/— spec tests + VM harnessweb/— minimal admin/management UI (connect + read + send tx)
name() -> Stringsymbol() -> Stringbase_uri() -> Stringtoken_uri(TokenUri) -> Stringtotal_supply() -> u64balance_of(BalanceOf) -> u64owner_of(OwnerOf) -> Accountget_approved(GetApproved) -> Accountis_approved_for_all(IsApprovedForAll) -> bool
approve(ApproveCall)set_approval_for_all(SetApprovalForAllCall)transfer_from(TransferFromCall)
transfer(events::Transfer)approval(events::Approval)approval_for_all(events::ApprovalForAll)
- 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/drc721_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/drc721_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:
{
"base_uri": "ipfs://example-collection/",
"initial_tokens": [
{ "account": { "External": "26brdzqNXEG1jTzCubJAPhks18bSSDY4n21ZW6VLYkCv6bBUdBAZZAbn1Coz1LPBYc4uEekBbzFnZvhL9untGCqRamhZS2cBV51fdZog3qkP3NbMEaqgNMcKEahAFV8t2Cke" }, "token_id": "1" }
]
}Notes:
Externalis a public account (base58).- Token IDs are
u64and accepted as JSON strings (to avoid JS precision issues).base_uriis optional; leave it empty or omit it to disabletoken_uri.token_uriis computed asbase_uri + token_id, so include a trailing/if you want.../1.
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_tokens list in Init.
The repo includes a small spec test-suite that runs the contract in dusk-vm and
asserts the classic ERC721 behaviors (ownership, approvals, 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/drc721.wasm - Build the helper contract to
target/wasm32-unknown-unknown/release/drc721_test_caller.wasm - Run
cargo test -p drc721-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.