Smart contracts in Ω-chain are programs in OVM Byte Code, which is interprets and executed by The Omega Virtual Machine (OVM). OVM Byte Code is a low level programming language. It is designed to be printable in order to ease reading and debugging. An Ω smart contract program consists of OVM instructions. Each OVM instruction begins with an one-byte op code, followed by a variable length parametes, and ends with a new-line character ('\n', ASCI code 10).

The OVM instruction set is as follows:
Op CodeMnemonicParametersOperation
AEVAL8An inverse Poland expressionEvaluate the inverse Poland expression (8-bit data) stored the result to the destination.
BEVAL16An inverse Poland expressionEvaluate the inverse Poland expression (16-bit data) stored the result to the destination.
CEVAL32An inverse Poland expressionEvaluate the inverse Poland expression (32-bit data) stored the result to the destination.
DEVAL64An inverse Poland expressionEvaluate the inverse Poland expression (64-bit data) stored the result to the destination.
EEVAL256An inverse Poland expressionEvaluate the inverse Poland expression (256-bit data) stored the result to the destination.
FCONV{dataType}{addrOperand}{dataType}{addrOperand}Convert between different types of data
GHASH{addrOperand}{addrOperand}{patOperand}Sha-256 hash
HHASH160{addrOperand}{addrOperand}{patOperand}{patOperand}?Ripemd 160 hash (btcutil style or bare)
ISIGCHECK{addrOperand}{patOperand}{patOperand}{addrOperand}Signature verification
KIF{patOperand}{patOperand}Conditional jump
LCALL{patOperand}{patOperand}+Function call
MEXEC{addrOperand}{patOperand}{addrOperand}{addrOperand}{patOperand}*Execute another contract
NLOAD{addrOperand}{patOperand}Load persistent data
OSTORE{patOperand}{regexp.MustCompile(`^[rRBWDQHhkK]|(L[0-9]+)`)}{patOperand}Store persistent data
PDEL{patOperand}Delete persistent data
QLIBLOAD{patOperand}{patOperand}Load a library
RMALLOC{addrOperand}{patOperand}Memory allocation in global space
SALLOC{addrOperand}{patOperand}Memory allocation in local space
TCOPY{addrOperand}{addrOperand}{patOperand}Data copy
UCOPYIMM{addrOperand}{dataType}{patOperand}Immediate data copy<
VSELFDESTRUCT{patOperand}Self destruction
XREVERTFail and stop execution
YRETURNReturn from function call
aRECEIVED{addrOperand}Current outpoint
bTXFEE{addrOperand}{patOperand}Minum transaction fees
cGETCOIN{addrOperand}Token received
dNULOP
eSPEND{patOperand}{patOperand}Spend the contract's coin (add an input to the transaction)
fADDRIGHTDEF{addrOperand}{addrOperand}Add a right definition to the transaction
gADDTXOUT{addrOperand}{addrOperand}Add an output to the transaction
hGETDEFINITION{addrOperand}{patOperand}{patOperand}Get a definition
iGETUTXO{addrOperand}{patOperand}{patOperand}Get an UTXO
jMINT{addrOperand}{patOperand}{patOperand}{patOperand}Mint a coin
kMETA{addrOperand}{patOperand}{patOperand}Get contract's meta data
lTIME{addrOperand}Current block timestamp
mHEIGHT{addrOperand}Current block height
nTXIOCOUNTCurrent block height
zSTOPStop execution

Where, in regular expressions:
patOperand = @?n?(g?i+)?(([kK]?[xa-f]?[0-9a-f]+)|([0-9]+))(\'[0-9]+)?(\"[0-9]+)?,
addrOperand = n?g?i+(([xa-f]?[0-9a-f]+)|([0-9]+))(\'[0-9]+)?(\"[0-9]+)?,
dataType = [rRBWDQHhkKL]

Memory Model:

In OVM, memory is organized as stack of heaps (frames). When a contract starts, a memory heap is created and placed in the stack. Each time when a function is called (execution of CALL instruction), a new heap (frame) is created and pushed into the stack. When execution control returns from the function (execution of RETURN instruction), the frame if popped from the stack. By using heap of stacks, the need of garbage collection is reduced.

OVM uses 64-bit address with the higher 32 bits for stack level and lower 32 bits for offset within a frame. OVM code can directly memory locations in local frame (the present top-of-stack frame) and global frame (the bottom-of-stack frame). Any other memory location can only be addressed indirectly. Syntax for direct address is: g?i{NUMBER}, where g is for global frame. This i5 represents the memory location of 5-th byte in the top-of-stack frame, and gi20 represents the memory location of 20-th byte from current lib base in the global frame (frame 0).

For indirect addressing, the syntax is: g?i{2,6}{NUMBER}, with each i for one level of deference. E.g, ii5 represents the memory location reference by the address stored at the 64-bit location begining at 5-th byte in the top-of-stack frame.

An address may be modified by a ' (single quotation) or " (double quotation) modifier as offsets to first and last deferernce when addressing involves multiple deferences.

Execution Flow

OVM maintains an instruction counter pointing to the next instruction to be executed. Usually, the instruction counter will increase by 1 after execution of an instruction. CALL, IF, RETURN, LIBLOAD instructions will alter the flow of execution as follows:

IF: IF instruction has two parameters, the first is a byte data, the second is offset to instruction counter. OVM evaluates the first parameter, if it is not zero, OVM adds the second parameter to the instruction counter (relative jump). Otherwise, instruction counter increases by 1 (normal flow).

CALL: CALL instruction has two or more parameters. The first parameter is either 0 or a 20-byte lib address. If it is 0, the second parameter indicates an offset from the current instruction as entry of the function call. If it is not 0, the control flow goes to the entry of the lib indicated by the lib address and the second parameters is passed as a function name.

RETURN: RETURN instruction sets the instruction counter to the instruction following the CALL instruction.

LIBLOAD: LIBLOAD loads a contract indicated by the second parameter (the first parameter is access control flags), appends the instructions to the current program and immediately execute a CALL to the lib with 1 as function name. The lib is expected to perform one-time lib initialization and return. If the lib has already been loaded before, nothing is done.

Passing parameters:

Smart contract execution can be trigged by a script in a transaction's output. The script begings with 0x88, followed by 20-byte contract address, and varialble length parameters. OVM loads the contract code indicated by the address, sets instruction counter to 0, create and initialize frame 0. The first 4 bytes of frame 0 contains length of parameters, the next 4 bytes of frame 0 is 0. Starting at byte 8 of frame 0 is the parameter. Thus the address of contract parameter is gi0"8. Conventionally, the first 4 bytes of parameters is function name.

Smart contract execution can also be trigged by a direct RPC call. User may send an RPC request to a node containing a script in the format as described above. The node will execute and sends result back to the user. However, nothing will be recorded in the block chain database.

When contract execution ends normally, the OVM expects the first 4 bytes of frame 0 contains length of result which is followed by the result. The result will be ignore if the smart contract is trigged in a transaction.

With a function call, a new frame is created. Similarly, the first 4 bytes of the frame contains length of parameters, the next 4 bytes of frame is the frame's ID. Starting at byte 8 of the frame is the parameter. Thus the address of a function's parameters is always i0"8. If the function call is a local call (first parameter is 0), starting with parameter 3, each item is considered as a 64-bit data and passed to the function. If the function call is a call to another lib, parameter 2 is considered as 4-byte function name and passed first. Then the rest as 64-bit parameter data.

If a function is to return data back to the caller, the function should take some addresses as parameters. The caller should supply these addresses and the necessary memory. The function will store the results to these addresses. A function should never return an address in the current frame as the frame will be destroyed when the function returns.

A smart contract may triger execution of another smart contract through EXEC instruction. The difference betweeen EXEC and LIBLOAD/CALL instruction is that EXEC will cause execution in the new contract's context while LIBLOAD/CALL will execute in the current contract context. Circular EXEC is not allowed while recurcive calls among loaded libs are permitted.

Inverse Poland Expression:

The EVAL instructions (EVAL8, EVAL16, EVAL32, EVAL64, EVAL256) take inverse Poland expression, evaluate it and store the result to destination. The first item in the expression is already an address as destination. The rest items are evaluated as a normal inverse Poland expression. When evaluation is done, the bottom of evaluation stack is considered as the result and store to the destination. Allowed operators are:

OperatorFunctionStack PopsStack PushesException
+,-,*,/,%Math ops21
[,]Left, right shift21Not for EVAL256
|,&,^Bitwise OR, AND, XOR21
~Bitwise NOT11
?Select31
>,<,=,!,(,)Comparison: >, <, ==, !=, <=, >=21
uUnsigned. Next op is unsiged.00Not for EVAL256
#Pow.21
Operands always end with a comma(,). Generally, operands have the format as: @?n?(g?i+)?(([xa-f]?[0-9a-f]+)|([0-9]+))(\'[0-9]+)?(\"[0-9]+)?,
'@' indicate an address is pushed into the stack, instead of data at the address, it is only for EVAL64 and EVAL256.
'n' indicate a negative number is to be pushed into the stack.
'g' is global memory indicator, 'i' is deferencer. Without 'g' and 'i' indicator, the data in the operand is pushed to the stack.
Data following 'i' is considered an address offset. If 'g' indicator is present, it is considered as an offset in global space (if lib code is being executed, it is the lib's global frame).
If (\'[0-9]+) section is present, when evaluating (g?i+)?(([xa-f][0-9a-f]+)|([0-9]+)), the OVM would evaluate (g?i)(([xa-f][0-9a-f]+)|([0-9]+)) first, add the number in (\'[0-9]+) to the result and perform the rest deferences.
If (\"[0-9]+) section is present, the OVM would perform all addressings in (g?i+)(([xa-f][0-9a-f]+)|([0-9]+))(\'[0-9]+)?, add the number in (\"[0-9]+) to the result as final address, and push the data at that address to the stack.
'x' indicate the digits follows is a hex number. If a numer begings with [a-f], its is a hex numer without need of an 'x'.

Interact with Transaction:

SPEND instruction causes an item added to the current transaction's input list.

ADDTXOUT instruction causes an item added to the current transaction's output list.

MINT instruction causes an item added to the current coinbase's output list.

ADDRIGHTDEF instruction causes an item added to the current transaction's definition list.

RECEIVED instruction loads outpoint representing the current transaction output.

GETCOIN instruction loads the token passed to the current transaction output.

TXFEE returns the minimum transaction fees requried for the current transaction.

GETDEFINITION returns the definition indicated by the hash parameter.

GETUTXO returns the definition indicated by the outpoint parameter.

META returns the requested contract meta data.

TIME returns the block timestamp.

HEIGHT returns the block height.

TXIOCOUNT returns current transaction's input and output count.