DVM-BASIC Programming Guide
DVM-BASIC is DERO's smart contract programming language - a blockchain-optimized BASIC variant that's easy to learn yet powerful enough for complex dApps with privacy features.
Source: dvm/ - Virtual Machine implementation
Language Features
- Line-numbered syntax (like GW-BASIC)
- Strong typing:
Uint64andString - Built-in blockchain functions
- Privacy-preserving operations
- Deterministic execution
Quick Start
Function Initialize() Uint64
10 STORE("owner", SIGNER())
20 STORE("counter", 0)
30 RETURN 0
End Function
Function Increment() Uint64
10 DIM current as Uint64
20 LET current = LOAD("counter")
30 STORE("counter", current + 1)
40 RETURN 0
End FunctionAuthorization patterns
SIGNER() returns the wallet address that sent the current transaction — Captain's words: "may not be the owner of the SC." It coincides with the owner during Initialize (canonical pattern below) but on every other call you must check explicitly. If your contract has no stored-owner gate, anyone can call UpdateCode and overwrite your logic — the DVM does not gate UpdateCode at the protocol level.
The canonical pattern: store the owner during Initialize, then gate every privileged function with IF LOAD("owner") == SIGNER() THEN ....
Function Initialize() Uint64
10 STORE("owner", SIGNER())
20 RETURN 0
End Function
Function UpdateOwner(new_owner String) Uint64
10 IF LOAD("owner") == SIGNER() THEN GOTO 30
20 RETURN 1
30 STORE("owner", ADDRESS_RAW(new_owner))
40 RETURN 0
End FunctionWithout line 10, anyone can call UpdateOwner and seize the contract.
Data Types & Variables
| Type | Range | Default | Usage |
|---|---|---|---|
Uint64 | 0 to 18,446,744,073,709,551,615 | 0 | Numbers, balances, counts |
String | Variable (size limits apply) | "" | Text, addresses, keys |
Declare variables:
10 DIM counter as Uint64
20 DIM name, symbol as StringOperators
| Type | Operators |
|---|---|
| Arithmetic | + - * / % |
| Bitwise | & | ^ ! >> << |
| Comparison | > >= < <= == != |
| String | + (concat), ==, != |
Control Flow
IF-THEN-ELSE:
10 IF value > 100 THEN GOTO 30 ELSE GOTO 50Loops with GOTO:
10 LET counter = 0
20 LET counter = counter + 1
30 IF counter < 10 THEN GOTO 20Comments
' Single-line comment
// Alternative single-line
/* Multi-line
comment */Functions
Syntax:
Function Name(param1 Type, param2 Type) ReturnType
10 RETURN value
End FunctionVisibility:
- Uppercase first letter → Public (callable externally)
- Lowercase first letter → Private (internal only)
Return values:
0= success- Non-zero = error code
Blockchain Functions
State Management
| Function | Purpose |
|---|---|
STORE(key, value) | Save to blockchain state |
LOAD(key) | Read from blockchain state |
EXISTS(key) | Check if key exists |
Identity & Transaction
| Function | Purpose |
|---|---|
SIGNER() | Get transaction sender address |
TXID() | Get current transaction ID |
ADDRESS_RAW(string) | Convert address string to raw format |
IS_ADDRESS_VALID(string) | Validate address format |
Asset Operations
| Function | Purpose |
|---|---|
SEND_DERO_TO_ADDRESS(addr, amount) | Transfer DERO |
SEND_ASSET_TO_ADDRESS(addr, amount, scid) | Transfer asset/token |
DEROVALUE() | Get DERO sent in transaction |
ASSETVALUE(scid) | Get asset sent in transaction |
Blockchain Info
| Function | Purpose |
|---|---|
BLOCK_HEIGHT() | Current block height |
BLOCK_TIMESTAMP() | Current block timestamp |
SCID() | This contract's ID |
Cryptographic
| Function | Purpose |
|---|---|
SHA256(data) | Compute SHA256 hash |
KECCAK256(data) | Compute Keccak256 hash |
Best Practices
- Security - Always validate inputs and permissions
- Gas efficiency - Minimize STORE/LOAD operations
- Line spacing - Use increments of 10 for future insertions
- Error codes - Return meaningful error codes
- Testing - Use Simulator before deployment
Example: Token Contract
Function Initialize() Uint64
10 STORE("owner", SIGNER())
20 STORE("supply", 1000000)
30 STORE("balance:" + SIGNER(), 1000000)
40 RETURN 0
End Function
Function Transfer(to String, amount Uint64) Uint64
10 DIM sender as String
20 DIM sender_bal, recipient_bal as Uint64
30 LET sender = SIGNER()
40 IF IS_ADDRESS_VALID(to) != 1 THEN GOTO 200
50 IF amount <= 0 THEN GOTO 200
60 LET sender_bal = LOAD("balance:" + sender)
70 IF sender_bal < amount THEN GOTO 200
80 IF EXISTS("balance:" + ADDRESS_RAW(to)) THEN GOTO 100
90 STORE("balance:" + ADDRESS_RAW(to), 0)
100 LET recipient_bal = LOAD("balance:" + ADDRESS_RAW(to))
110 STORE("balance:" + sender, sender_bal - amount)
120 STORE("balance:" + ADDRESS_RAW(to), recipient_bal + amount)
130 RETURN 0
200 RETURN 1 ' Error
End Function
Function BalanceOf(address String) Uint64
10 IF EXISTS("balance:" + ADDRESS_RAW(address)) THEN GOTO 30
20 RETURN 0
30 RETURN LOAD("balance:" + ADDRESS_RAW(address))
End FunctionLearn More
- DERO Virtual Machine - DVM architecture
- Token Contract Tutorial - Build a full token
- Smart Contract Examples - More examples
Tip: The DVM-BASIC language evolves with DERO. Check official docs for updates!
Related Pages
Smart Contract Examples:
- Token Contract - Build a private token
- Assets Exchange - Token swap contract
- Lottery Contract - Decentralized lottery
- Name Service - Register usernames
Understanding the DVM:
- DERO Virtual Machine - DVM architecture
- Private Smart Contracts - Contract privacy features
Deploy & Test:
- Wallet RPC API - Deploy contracts programmatically
- Running a Node - Setup testnet for development