What is Minichain Assembly?
Minichain uses a custom assembly language that compiles to bytecode for a register-based virtual machine with:- 16 registers (R0-R15) for temporary values
- 40+ opcodes covering arithmetic, logic, memory, storage, and control flow
- Gas metering on every operation
- Persistent storage using SLOAD/SSTORE
- Human-readable syntax with labels and directives
Your First Contract: A Simple Counter
-
Understand the Requirements
We’ll build a counter contract that:
- Stores a counter value in storage slot 0
- Increments the counter by 1 each time it’s called
- Uses minimal gas
-
Write the Assembly Code
Create a file called
counter.asm: -
Understand Each Instruction
Let’s break down what each line does:
Line 1:
.entry main- A directive that declares the entry point
- Execution starts at the
mainlabel - Required for all contracts
LOADI R0, 0- LOADI = Load Immediate
- Loads the constant value
0into register R0 - R0 now holds the storage slot number we want to access
- Gas cost: 2
SLOAD R1, R0- SLOAD = Storage Load
- Reads from the storage slot specified by R0 (slot 0)
- Stores the retrieved value in R1
- If slot is empty, returns 0
- Gas cost: 100
LOADI R2, 1- Loads the constant
1into register R2 - This is the increment amount
- Gas cost: 2
ADD R1, R1, R2- ADD = Addition
- Adds R1 + R2, stores result in R1
- R1 now contains the incremented counter
- Gas cost: 2
SSTORE R0, R1- SSTORE = Storage Store
- Writes the value in R1 to the storage slot specified by R0
- Persists the new counter value
- Gas cost: 20,000 (first write) or 5,000 (subsequent writes)
HALT- Stops execution successfully
- Returns control to the VM
- Gas cost: 0
-
Calculate Total Gas Cost
First call (storage slot empty):
Subsequent calls:Always set gas-limit higher than expected: 80,000 provides safety margin.
-
Compile the Contract
The assembly is automatically compiled during deployment, but you can verify it compiles correctly:
The compiler performs:
- Lexing: Tokenizes the source code
- Parsing: Builds an Abstract Syntax Tree (AST)
- Two-pass compilation:
- Pass 1: Collect labels and constants
- Pass 2: Emit bytecode with resolved references
-
Deploy and Test
Deploy the contract:
Call it multiple times:The counter increments each time!
Adding Features: Counter with Custom Increment
Let’s enhance the contract to accept a custom increment amount via calldata:- LOG R1: Emits a log event with the value in R1 (gas cost: 2)
Understanding Register Usage
Registers are like temporary variables:- Use R0-R7 for frequently accessed values
- Reserve R14-R15 for temporary calculations
- Document register usage with comments
- Reuse registers when values are no longer needed
Common Patterns
Pattern: Conditional Logic
Pattern: Loops (Using Labels)
Pattern: Storage Mapping
Instruction Set Quick Reference
Arithmetic
| Instruction | Description | Gas |
|---|---|---|
ADD Rd, Rs1, Rs2 | Rd = Rs1 + Rs2 | 2 |
SUB Rd, Rs1, Rs2 | Rd = Rs1 - Rs2 | 2 |
MUL Rd, Rs1, Rs2 | Rd = Rs1 × Rs2 | 2 |
DIV Rd, Rs1, Rs2 | Rd = Rs1 ÷ Rs2 | 4 |
MOD Rd, Rs1, Rs2 | Rd = Rs1 % Rs2 | 4 |
Comparison
| Instruction | Description | Gas |
|---|---|---|
EQ Rd, Rs1, Rs2 | Rd = (Rs1 == Rs2) | 2 |
LT Rd, Rs1, Rs2 | Rd = (Rs1 < Rs2) | 2 |
GT Rd, Rs1, Rs2 | Rd = (Rs1 > Rs2) | 2 |
ISZERO Rd | Rd = (Rd == 0) | 2 |
Storage
| Instruction | Description | Gas |
|---|---|---|
SLOAD Rd, Rkey | Load from storage | 100 |
SSTORE Rkey, Rval | Write to storage | 5,000-20,000 |
Control Flow
| Instruction | Description | Gas |
|---|---|---|
JUMP Rtarget | Unconditional jump | 8 |
JUMPI Rcond, Rtarget | Jump if Rcond != 0 | 8 |
HALT | Stop execution (success) | 0 |
REVERT | Stop execution (failure) | 0 |
Immediates
| Instruction | Description | Gas |
|---|---|---|
LOADI Rd, imm | Load constant | 2 |
MOV Rd, Rs | Copy register | 2 |
Context
| Instruction | Description | Gas |
|---|---|---|
CALLER Rd | Get transaction sender | 2 |
ADDRESS Rd | Get contract address | 2 |
CALLVALUE Rd | Get transaction value | 2 |
BLOCKNUMBER Rd | Get block number | 2 |
TIMESTAMP Rd | Get block timestamp | 2 |
GAS Rd | Get remaining gas | 2 |
Next Steps
Now that you can write basic contracts:- Learn debugging techniques in Debugging Contracts
- Explore testing patterns in Testing Guide
- See more examples in Contract Examples
- Reference all opcodes in Opcode Reference
Tips for Writing Efficient Contracts
- Minimize storage operations - SSTORE is expensive (5,000-20,000 gas)
- Reuse registers - Avoid loading the same constants multiple times
- Use labels for code organization - Makes assembly more readable
- Add comments - Explain what each section does
- Test with gas limits - Monitor actual gas usage
- Use LOG for debugging - Emit values during development