fate
FATE
The fast æternity transaction engine.
Design
The high level machine (or the fast æternity transaction engine) has æternity transactions as its basic operations and it operates directly on the state tree of the æternity chain. This is a new paradigm in blockchain virtual machine specifications which makes it possible to create type safe and efficient implementations of the machine.
Every operation is typed and all values are typed (either by being stored in a typed memory or by a tag). Any type violation results in an exception and reverts all state changes. In version 1.0 there will be no catch instruction.
In addition to normal machine instructions, such as ADD, the machine also has support for constructing most of the transactions available on the æternity chain from native low level chain transaction instructions.
The instruction memory is divided into functions and basic blocks. Only basic blocks can be indexed and used as jump destinations.
There are instructions to operate on the chain state tree in a safe and formalized way.
FATE is "functional" in the sense that "updates" of data structures, such as tuples, lists or maps do not change the old values of the structure. Instead a new version is created, unless specific operations to write to the contract store are used.
FATE does have the ability to write the value of an operation back to the same register or stack position as one of the arguments, in effect updating the memory. Thus, any other references to the structure before the operation will have the same structure as before the operation.
Objectives
Type safety
FATE solves some fundamental problems programmers run into when coding for Ethereum: integer overflow, weak type checking and poor data flow. FATE checks all arithmetic operations to keep the right meaning of it. Also you can't implicitly cast types (eg integers to booleans).
In EVM contracts are not typed. When calling a function, EVM will try to find which function you wanted to use by looking at the data that you send into the code. In FATE, you have actual functions and the functions have types - function call has to match the function type.
FATE ultimately makes a safer coding platform for smart contracts.
Rich data types
FATE has more built in data types: like maps, lists.
Faster transactions, smaller code size
Having a higher level instructions makes the code deployed smaller and it reduces the blockchain size. Smaller code and smaller hashes also keeps a blockchain network from clogging up and results in cheaper transactions.
Components
Machine State
Current contract: Address
Current owner: Address
Caller: Address
Code: Code of current contract
Memory: Several components as defined below
CF, current function: Hash of current function
CBB, current basic block: Index of current basic block.
EC, Execution continuation: A list of instructions left in the current basic block.
Memory
The machine memory is divided into:
The chain top (block height, etc)
Event stream
The account state tree
The contract store
The execution/code memory
Execution stack (push/pop on call/return)
Accumulator stack (push/pop on instruction level)
Local storage/stack/environment/context (push/pop on let...in...end)
The execution memory
The code to execute is stored in the execution memory. The execution memory is a three level map. The key on the top level is a contract address. The second level is a map from function hashes to a map of basic blocks. The keys in the map of basic blocks are indices to basic blocks (a 0 based, dense enumeration). The values are lists of instructions.
When a contract is called the code of the contract is read from the state tree into the execution memory. At this point the machine implementation can deserialize the serialized version of FATE code into instructions and basic blocks.
The serialization format for FATE code is described in Appendix 1: Fate instruction set and serialization.
The chain
The chain "memory" contains information about the current block and the current iteration. These values are available through special instructions.
Beneficiary
Timestamp
(Block) Height
Difficulty
Gaslimit
Address
Balance
Caller
Value
The contract store
The permanent storage of a contract. Stored in the chain state tree. This is a key value store that is mapped to the contract state by the compiler.
The compiler can choose how to represent the contract state in the store. For instance, save the entire state under a single key (this is how it works in AEVM at the moment), or it could flatten any state records and store each field under a separate key.
The state tree
Contains all accounts, oracles and contracts on the chain. Most values such as account balances can be read directly through specific load instructions. Some values can be changed through transaction instructions.
The local storage
The local storage is a key value store. The key is a an integer. The value can be of any FATE type. The local store is local to a function call.
The accumulator stack
The accumulator stack is a stack of typed values. The top of the stack can be used as an argument to an operation. Values can be pushed to the stack and popped from the stack.
The execution stack
The execution stack contain return addresses as a tuple in the form of {contract address, function hash, and basic block index}.
The event stream
A contract can emit events similar to the EVM.
Types
The machine supports the following types:
Integer (signed arbitrary precision integers)
Boolean (true | false)
Strings (arbitrary size byte arrays)
Bytes (fixed size byte arrays)
Bits (An arbitrary size bitmap)
Address (A pointer into the state tree)
Contract Address (A pointer to a contract)
Oracle (A pointer to an oracle)
Oracle Query (A pointer to an oracle query)
Channel (A pointer to a channel)
Tuples (a typed series of values)
Lists (a list of values of a specific type)
Maps (a key value store)
Store Map (a key value store mapped to the contract state)
Variant Types (a set of tagged and typed values)
Type (a representation of a FATE type)
These types can be used as argument and return types of functions and also as the type of the elements in the contract store.
Integer
The type Integer, is used for any integer, infinitely large or small (below zero).
Examples:
Boolean
The Boolean type only has two values, true or false.
Examples (all of them):
Operations on booleans include:
and
,or
,not
conditional jumps
Addresses, Contract Addresses, Oracles, Oracle Querries, Channels
Values of any address type are 32-byte (256-bit) pointers to entities on the chain (Accounts, Oracles, Contracts, etc)
Examples:
Strings
Strings are stored as byte arrays. From VM version FATE_02
they are strictly UTF-8 encoded unicode characters. In particular operations String.to_list
and String.from_list
ensure that they only contain well formed code points.
Examples:
Bytes
In VM versions FATE_01
and FATE_02
only fixed (size known at compile time) size byte arrays exist. With the change to Strings, making them UTF-8 encoded byte arrays, there is a need for general arbitrary length byte arrays. These are introduced in FATE_03
- and a couple of new operations handling (and converting) byte arrays are added. Technical note: the bytes type was {bytes, N} / bytes(n)
- to change as little as possible arbitrary size byte arrays have the type {bytes, -1} / bytes()
.
Tuples
Tuples have an arity indicating the number of elements in the tuple. Each element in the tuple has a type. The 0-tuple is also sometimes called unit. The maximum number of elements in the tuple is 255 (included).
Examples:
Lists
Lists are monomorphic series of values. Hence lists have a type. There is also an empty list (or Nil).
Examples:
Maps
Maps are monomorphic key value stores, that is the key is always the same type for all elements in a map and the value has the same type in all mappings in a map. The key can have any type except a map. The value can have any type including a map.
Examples:
Type: Map(Integer, String)
Type: Map(String, Map(String, Integer))
Variant Types
The variant type is a type consisting of a list of sizes and a tag (index) where each tag represents a series of values of specified types. For example you could have the Option type which could be None or Some(Integer). The sizes of the variant are 0 and 1 (there are two variants), The value None would be indicated by tag 0. The value Some(42) would be represented by tag 1 followed by the integer 42.
Examples:
Note that the tuple syntax for the elements does not indicate a Fate tuple but a series of values.
TypeRep
A TypeRep is the representation of a type as a value. A TypeRep is one of
integer
boolean
any
{list, T}
{tuple, Ts}
address
contract
oracle
oracle_query
channel
bits
{bytes, N}
{map, K, V}
string
{variant, ListOfVariants}
{tvar, N}
where T, K and V are TypeReps, Ts is a list of TypeReps ([T1, T2, ... ]), and ListOfVariants is a list ([]) of tuples of TypeReps ([{tuple, [Ts1]}, {tuple, [Ts2]} ... ]). N is a byte (0...255).
Operations
All operations are typed. An operand can be the accumulator, an immediate, a name, a reference to a field in the state tree, or a reference to the contract state. The operand must be of the right type.
Operands
Operand specifiers are
immediate
arg
var
a (accumulator == stack 0)
The specifiers are encoded as
immediate
11
var
10
arg
01
stack
00
Operand specifiers for operations with 1 to 4 arguments are stored in the byte following the opcode. Operand specifiers for operations with 5 to 8 arguments are stored in the two bytes following the opcode. Note that for many operation the first argument (arg0) is the destination for the operation.
bit:
7
6
5
4
3
2
1
0
bit:
7
6
5
4
3
2
1
0
Unused arguments should be set to 0.
E.g. an a := immediate + a would have the bit pattern 00 11 00 00.
Each use of the accumulator pops an argument from the stack. Writing to the accumulator pushes a value to the stack.
Operations
Description of operations
RETURN
Return from function call, top of stack is return value . The type of the retun value has to match the return type of the function.
{}
any
FATE_01
RETURNR
Arg0
Push Arg0 and return from function. The type of the retun value has to match the return type of the function.
{any}
any
FATE_01
CALL
Arg0
Call the function Arg0 with args on stack. The types of the arguments has to match the argument typs of the function.
{string}
any
FATE_01
CALL_R
Arg0 Identifier Arg2 Arg3 Arg4
Remote call to contract Arg0 and function Arg1 of type Arg2 => Arg3 with value Arg4. The types of the arguments has to match the argument types of the function.
{contract,string,typerep,typerep,integer}
any
FATE_01
CALL_T
Arg0
Tail call to function Arg0. The types of the arguments has to match the argument typs of the function. And the return type of the called function has to match the type of the current function.
{string}
any
FATE_01
CALL_GR
Arg0 Identifier Arg2 Arg3 Arg4 Arg5
Remote call with gas cap in Arg4. Otherwise as CALL_R.
{contract,string,typerep,typerep,integer,integer}
any
FATE_01
JUMP
Integer
Jump to a basic block. The basic block has to exist in the current function.
{integer}
none
FATE_01
JUMPIF
Arg0 Integer
Conditional jump to a basic block. If Arg0 then jump to Arg1.
{boolean,integer}
none
FATE_01
SWITCH_V2
Arg0 Integer Integer
Conditional jump to a basic block on variant tag.
{variant,integer,ingeger}
none
FATE_01
SWITCH_V3
Arg0 Integer Integer Integer
Conditional jump to a basic block on variant tag.
{variant,integer,integer,ingeger}
none
FATE_01
SWITCH_VN
Arg0 [Integers]
Conditional jump to a basic block on variant tag.
{variant,{list,integer}}
none
FATE_01
CALL_VALUE
Arg0
The value sent in the current remote call.
{}
integer
FATE_01
PUSH
Arg0
Push argument to stack.
{any}
any
FATE_01
DUPA
Duplicate top of stack.
{any}
any
FATE_01
DUP
Arg0
push Arg0 stack pos on top of stack.
{any}
any
FATE_01
POP
Arg0
Arg0 := top of stack.
{integer}
integer
FATE_01
INCA
Increment accumulator.
{integer}
integer
FATE_01
INC
Arg0
Increment argument.
{integer}
integer
FATE_01
DECA
Decrement accumulator.
{integer}
integer
FATE_01
DEC
Arg0
Decrement argument.
{integer}
integer
FATE_01
ADD
Arg0 Arg1 Arg2
Arg0 := Arg1 + Arg2.
{integer,integer}
integer
FATE_01
SUB
Arg0 Arg1 Arg2
Arg0 := Arg1 - Arg2.
{integer,integer}
integer
FATE_01
MUL
Arg0 Arg1 Arg2
Arg0 := Arg1 * Arg2.
{integer,integer}
integer
FATE_01
DIV
Arg0 Arg1 Arg2
Arg0 := Arg1 / Arg2.
{integer,integer}
integer
FATE_01
MOD
Arg0 Arg1 Arg2
Arg0 := Arg1 mod Arg2.
{integer,integer}
integer
FATE_01
POW
Arg0 Arg1 Arg2
Arg0 := Arg1 ^ Arg2.
{integer,integer}
integer
FATE_01
STORE
Arg0 Arg1
Arg0 := Arg1.
{any}
any
FATE_01
SHA3
Arg0 Arg1
Arg0 := sha3(Arg1).
{any}
hash
FATE_01
SHA256
Arg0 Arg1
Arg0 := sha256(Arg1).
{any}
hash
FATE_01
BLAKE2B
Arg0 Arg1
Arg0 := blake2b(Arg1).
{any}
hash
FATE_01
LT
Arg0 Arg1 Arg2
Arg0 := Arg1 < Arg2.
{integer,integer}
boolean
FATE_01
GT
Arg0 Arg1 Arg2
Arg0 := Arg1 > Arg2.
{integer,integer}
boolean
FATE_01
EQ
Arg0 Arg1 Arg2
Arg0 := Arg1 = Arg2.
{integer,integer}
boolean
FATE_01
ELT
Arg0 Arg1 Arg2
Arg0 := Arg1 =< Arg2.
{integer,integer}
boolean
FATE_01
EGT
Arg0 Arg1 Arg2
Arg0 := Arg1 >= Arg2.
{integer,integer}
boolean
FATE_01
NEQ
Arg0 Arg1 Arg2
Arg0 := Arg1 /= Arg2.
{integer,integer}
boolean
FATE_01
AND
Arg0 Arg1 Arg2
Arg0 := Arg1 and Arg2.
{boolean,boolean}
boolean
FATE_01
OR
Arg0 Arg1 Arg2
Arg0 := Arg1 or Arg2.
{boolean,boolean}
boolean
FATE_01
NOT
Arg0 Arg1
Arg0 := not Arg1.
{boolean}
boolean
FATE_01
TUPLE
Arg0 Integer
Arg0 := tuple of size = Arg1. Elements on stack.
{integer}
tuple
FATE_01
ELEMENT
Arg0 Arg1 Arg2
Arg1 := element(Arg2, Arg3).
{integer,tuple}
any
FATE_01
SETELEMENT
Arg0 Arg1 Arg2 Arg3
Arg0 := a new tuple similar to Arg2, but with element number Arg1 replaced by Arg3.
{integer,tuple,any}
tuple
FATE_01
MAP_EMPTY
Arg0
Arg0 := #{}.
{}
map
FATE_01
MAP_LOOKUP
Arg0 Arg1 Arg2
Arg0 := lookup key Arg2 in map Arg1.
{map,any}
any
FATE_01
MAP_LOOKUPD
Arg0 Arg1 Arg2 Arg3
Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3.
{map,any,any}
any
FATE_01
MAP_UPDATE
Arg0 Arg1 Arg2 Arg3
Arg0 := update key Arg2 in map Arg1 with value Arg3.
{map,any,any}
map
FATE_01
MAP_DELETE
Arg0 Arg1 Arg2
Arg0 := delete key Arg2 from map Arg1.
{map,any}
map
FATE_01
MAP_MEMBER
Arg0 Arg1 Arg2
Arg0 := true if key Arg2 is in map Arg1.
{map,any}
boolean
FATE_01
MAP_FROM_LIST
Arg0 Arg1
Arg0 := make a map from (key, value) list in Arg1.
{{list,{tuple,[any,any]}}}
map
FATE_01
MAP_SIZE
Arg0 Arg1
Arg0 := The size of the map Arg1.
{map}
integer
FATE_01
MAP_TO_LIST
Arg0 Arg1
Arg0 := The tuple list representation of the map Arg1.
{map}
list
FATE_01
IS_NIL
Arg0 Arg1
Arg0 := true if Arg1 == [].
{list}
boolean
FATE_01
CONS
Arg0 Arg1 Arg2
Arg0 := [Arg1] ++ Arg2.
{any,list}
list
FATE_01
HD
Arg0 Arg1
Arg0 := head of list Arg1.
{list}
any
FATE_01
TL
Arg0 Arg1
Arg0 := tail of list Arg1.
{list}
list
FATE_01
LENGTH
Arg0 Arg1
Arg0 := length of list Arg1.
{list}
integer
FATE_01
NIL
Arg0
Arg0 := [].
{}
list
FATE_01
APPEND
Arg0 Arg1 Arg2
Arg0 := Arg1 ++ Arg2.
{list,list}
list
FATE_01
STR_JOIN
Arg0 Arg1 Arg2
Arg0 := string Arg1 followed by string Arg2.
{string,string}
string
FATE_01
INT_TO_STR
Arg0 Arg1
Arg0 := turn integer Arg1 into a string.
{integer}
string
FATE_01
ADDR_TO_STR
Arg0 Arg1
Arg0 := turn address Arg1 into a string.
{address}
string
FATE_01
STR_REVERSE
Arg0 Arg1
Arg0 := the reverse of string Arg1.
{string}
string
FATE_01
STR_LENGTH
Arg0 Arg1
Arg0 := The length of the string Arg1.
{string}
integer
FATE_01
BYTES_TO_INT
Arg0 Arg1
Arg0 := bytes_to_int(Arg1)
{bytes}
integer
FATE_01
BYTES_TO_STR
Arg0 Arg1
Arg0 := bytes_to_str(Arg1)
{bytes}
string
FATE_01
BYTES_CONCAT
Arg0 Arg1 Arg2
Arg0 := bytes_concat(Arg1, Arg2)
{bytes,bytes}
bytes
FATE_01
BYTES_SPLIT
Arg0 Arg1 Arg2
Arg0 := bytes_split(Arg2, Arg1), where Arg2 is the length of the first chunk.
{bytes,integer}
bytes
FATE_01
INT_TO_ADDR
Arg0 Arg1
Arg0 := turn integer Arg1 into an address.
{integer}
address
FATE_01
VARIANT
Arg0 Arg1 Arg2 Arg3
Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack.
{integer,integer,integer}
variant
FATE_01
VARIANT_TEST
Arg0 Arg1 Arg2
Arg0 := true if variant Arg1 has the tag Arg2.
{variant,integer}
boolean
FATE_01
VARIANT_ELEMENT
Arg0 Arg1 Arg2
Arg0 := element number Arg2 from variant Arg1.
{variant,integer}
any
FATE_01
BITS_NONEA
push an empty bitmap on the stack.
{}
bits
FATE_01
BITS_NONE
Arg0
Arg0 := empty bitmap.
{}
bits
FATE_01
BITS_ALLA
push a full bitmap on the stack.
{}
bits
FATE_01
BITS_ALL
Arg0
Arg0 := full bitmap.
{}
bits
FATE_01
BITS_ALL_N
Arg0 Arg1
Arg0 := bitmap with Arg1 bits set.
{integer}
bits
FATE_01
BITS_SET
Arg0 Arg1 Arg2
Arg0 := set bit Arg2 of bitmap Arg1.
{bits,integer}
bits
FATE_01
BITS_CLEAR
Arg0 Arg1 Arg2
Arg0 := clear bit Arg2 of bitmap Arg1.
{bits,integer}
bits
FATE_01
BITS_TEST
Arg0 Arg1 Arg2
Arg0 := true if bit Arg2 of bitmap Arg1 is set.
{bits,integer}
boolean
FATE_01
BITS_SUM
Arg0 Arg1
Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap.
{bits}
integer
FATE_01
BITS_OR
Arg0 Arg1 Arg2
Arg0 := Arg1 v Arg2.
{bits,bits}
bits
FATE_01
BITS_AND
Arg0 Arg1 Arg2
Arg0 := Arg1 ^ Arg2.
{bits,bits}
bits
FATE_01
BITS_DIFF
Arg0 Arg1 Arg2
Arg0 := Arg1 - Arg2.
{bits,bits}
bits
FATE_01
BALANCE
Arg0
Arg0 := The current contract balance.
{}
integer
FATE_01
ORIGIN
Arg0
Arg0 := Address of contract called by the call transaction.
{}
address
FATE_01
CALLER
Arg0
Arg0 := The address that signed the call transaction.
{}
address
FATE_01
BLOCKHASH
Arg0 Arg1
Arg0 := The blockhash at height.
{integer}
variant
FATE_01
BENEFICIARY
Arg0
Arg0 := The address of the current beneficiary.
{}
address
FATE_01
TIMESTAMP
Arg0
Arg0 := The current timestamp. Unreliable, don't use for anything.
{}
integer
FATE_01
GENERATION
Arg0
Arg0 := The block height of the current generation.
{}
integer
FATE_01
MICROBLOCK
Arg0
Arg0 := The current micro block number.
{}
integer
FATE_01
DIFFICULTY
Arg0
Arg0 := The current difficulty.
{}
integer
FATE_01
GASLIMIT
Arg0
Arg0 := The current gaslimit.
{}
integer
FATE_01
GAS
Arg0
Arg0 := The amount of gas left.
{}
integer
FATE_01
ADDRESS
Arg0
Arg0 := The current contract address.
{}
address
FATE_01
GASPRICE
Arg0
Arg0 := The current gas price.
{}
integer
FATE_01
LOG0
Arg0
Create a log message in the call object.
{string}
none
FATE_01
LOG1
Arg0 Arg1
Create a log message with one topic in the call object.
{integer,string}
none
FATE_01
LOG2
Arg0 Arg1 Arg2
Create a log message with two topics in the call object.
{integer,integer,string}
none
FATE_01
LOG3
Arg0 Arg1 Arg2 Arg3
Create a log message with three topics in the call object.
{integer,integer,integer,string}
none
FATE_01
LOG4
Arg0 Arg1 Arg2 Arg3 Arg4
Create a log message with four topics in the call object.
{integer,integer,integer,integer,string}
none
FATE_01
SPEND
Arg0 Arg1
Transfer Arg1 coins to account Arg0. (If the contract account has at least that many coins.
{address,integer}
none
FATE_01
ORACLE_REGISTER
Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Arg6
Arg0 := New oracle with address Arg2, query fee Arg3, TTL Arg4, query type Arg5 and response type Arg6. Arg0 contains delegation signature.
{signature,address,integer,variant,typerep,typerep}
oracle
FATE_01
ORACLE_QUERY
Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Arg6 Arg7
Arg0 := New oracle query for oracle Arg1, question in Arg2, query fee in Arg3, query TTL in Arg4, response TTL in Arg5. Typereps for checking oracle type is in Arg6 and Arg7.
{oracle,any,integer,variant,variant,typerep,typerep}
oracle_query
FATE_01
ORACLE_RESPOND
Arg0 Arg1 Arg2 Arg3 Arg4 Arg5
Respond as oracle Arg1 to query in Arg2 with response Arg3. Arg0 contains delegation signature. Typereps for checking oracle type is in Arg4 and Arg5.
{signature,oracle,oracle_query,any,typerep,typerep}
none
FATE_01
ORACLE_EXTEND
Arg0 Arg1 Arg2
Extend oracle in Arg1 with TTL in Arg2. Arg0 contains delegation signature.
{signature,oracle,variant}
none
FATE_01
ORACLE_GET_ANSWER
Arg0 Arg1 Arg2 Arg3 Arg4
Arg0 := option variant with answer (if any) from oracle query in Arg1 given by oracle Arg0. Typereps for checking oracle type is in Arg3 and Arg4.
{oracle,oracle_query,typerep,typerep}
any
FATE_01
ORACLE_GET_QUESTION
Arg0 Arg1 Arg2 Arg3 Arg4
Arg0 := question in oracle query Arg2 given to oracle Arg1. Typereps for checking oracle type is in Arg3 and Arg4.
{oracle,oracle_query,typerep,typerep}
any
FATE_01
ORACLE_QUERY_FEE
Arg0 Arg1
Arg0 := query fee for oracle Arg1
{oracle}
integer
FATE_01
AENS_RESOLVE
Arg0 Arg1 Arg2 Arg3
Resolve name in Arg0 with tag Arg1. Arg2 describes the type parameter of the resolved name.
{string,string,typerep}
variant
FATE_01
AENS_PRECLAIM
Arg0 Arg1 Arg2
Preclaim the hash in Arg2 for address in Arg1. Arg0 contains delegation signature.
{signature,address,hash}
none
FATE_01
AENS_CLAIM
Arg0 Arg1 Arg2 Arg3 Arg4
Attempt to claim the name in Arg2 for address in Arg1 at a price in Arg4. Arg3 contains the salt used to hash the preclaim. Arg0 contains delegation signature.
{signature,address,string,integer,integer}
none
FATE_01
AENS_UPDATE
Arg0 Arg1 Arg2 Arg3 Arg4 Arg5
Updates name in Arg2 for address in Arg1. Arg3 contains optional ttl (of type Chain.ttl), Arg4 contains optional client_ttl (of type int), Arg5 contains optional pointers (of type map(string, pointee)). Arg0 contains delegation signature.
{signature,address,string,variant,variant,variant}
none
FATE_01
AENS_TRANSFER
Arg0 Arg1 Arg2 Arg3
Transfer ownership of name Arg3 from account Arg1 to Arg2. Arg0 contains delegation signature.
{signature,address,address,string}
none
FATE_01
AENS_REVOKE
Arg0 Arg1 Arg2
Revoke the name in Arg2 from owner Arg1. Arg0 contains delegation signature.
{signature,address,string}
none
FATE_01
BALANCE_OTHER
Arg0 Arg1
Arg0 := The balance of address Arg1.
{address}
integer
FATE_01
VERIFY_SIG
Arg0 Arg1 Arg2 Arg3
Arg0 := verify_sig(Hash, PubKey, Signature)
{bytes,address,bytes}
boolean
FATE_01
VERIFY_SIG_SECP256K1
Arg0 Arg1 Arg2 Arg3
Arg0 := verify_sig_secp256k1(Hash, PubKey, Signature)
{bytes,bytes,bytes}
boolean
FATE_01
CONTRACT_TO_ADDRESS
Arg0 Arg1
Arg0 := Arg1 - A no-op type conversion
{contract}
address
FATE_01
AUTH_TX_HASH
Arg0
If in GA authentication context return Some(TxHash) otherwise None.
{}
variant
FATE_01
ORACLE_CHECK
Arg0 Arg1 Arg2 Arg3
Arg0 := is Arg1 an oracle with the given query (Arg2) and response (Arg3) types
{oracle,typerep,typerep}
bool
FATE_01
ORACLE_CHECK_QUERY
Arg0 Arg1 Arg2 Arg3 Arg4
Arg0 := is Arg2 a query for the oracle Arg1 with the given types (Arg3, Arg4)
{oracle,oracle_query,typerep,typerep}
bool
FATE_01
IS_ORACLE
Arg0 Arg1
Arg0 := is Arg1 an oracle
{address}
bool
FATE_01
IS_CONTRACT
Arg0 Arg1
Arg0 := is Arg1 a contract
{address}
bool
FATE_01
IS_PAYABLE
Arg0 Arg1
Arg0 := is Arg1 a payable address
{address}
bool
FATE_01
CREATOR
Arg0
Arg0 := contract creator
{}
address
FATE_01
ECVERIFY_SECP256K1
Arg0 Arg1 Arg2 Arg3
Arg0 := ecverify_secp256k1(Hash, Addr, Signature)
{bytes,bytes,bytes}
bytes
FATE_01
ECRECOVER_SECP256K1
Arg0 Arg1 Arg2
Arg0 := ecrecover_secp256k1(Hash, Signature)
{bytes,bytes}
bytes
FATE_01
ADDRESS_TO_CONTRACT
Arg0 Arg1
Arg0 := Arg1 - A no-op type conversion
{address}
contract
FATE_01
BLS12_381_G1_NEG
Arg0 Arg1
Arg0 := BLS12_381.g1_neg(Arg1) - Negate a G1-value
{tuple}
tuple
FATE_02
BLS12_381_G1_NORM
Arg0 Arg1
Arg0 := BLS12_381.g1_normalize(Arg1) - Normalize a G1-value
{tuple}
tuple
FATE_02
BLS12_381_G1_VALID
Arg0 Arg1
Arg0 := BLS12_381.g1_valid(Arg1) - Check if G1-value is a valid group member
{tuple}
bool
FATE_02
BLS12_381_G1_IS_ZERO
Arg0 Arg1
Arg0 := BLS12_381.g1_is_zero(Arg1) - Check if G1-value is zero
{tuple}
bool
FATE_02
BLS12_381_G1_ADD
Arg0 Arg1 Arg2
Arg0 := BLS12_381.g1_add(Arg1, Arg2) - Add two G1-values
{tuple,tuple}
tuple
FATE_02
BLS12_381_G1_MUL
Arg0 Arg1 Arg2
Arg0 := BLS12_381.g1_mul(Arg1, Arg2) - Scalar multiplication for a G1-value (Arg1), and an Fr-value
{tuple,tuple}
tuple
FATE_02
BLS12_381_G2_NEG
Arg0 Arg1
Arg0 := BLS12_381.g2_neg(Arg1) - Negate a G2-value
{tuple}
tuple
FATE_02
BLS12_381_G2_NORM
Arg0 Arg1
Arg0 := BLS12_381.g2_normalize(Arg1) - Normalize a G2-value
{tuple}
tuple
FATE_02
BLS12_381_G2_VALID
Arg0 Arg1
Arg0 := BLS12_381.g2_valid(Arg1) - Check if G2-value is a valid group member
{tuple}
bool
FATE_02
BLS12_381_G2_IS_ZERO
Arg0 Arg1
Arg0 := BLS12_381.g2_is_zero(Arg1) - Check if G2-value is zero
{tuple}
bool
FATE_02
BLS12_381_G2_ADD
Arg0 Arg1 Arg2
Arg0 := BLS12_381.g2_add(Arg1, Arg2) - Add two G2-values
{tuple,tuple}
tuple
FATE_02
BLS12_381_G2_MUL
Arg0 Arg1 Arg2
Arg0 := BLS12_381.g2_mul(Arg1, Arg2) - Scalar multiplication for a G2-value (Arg2), and an Fr-value
{tuple,tuple}
tuple
FATE_02
BLS12_381_GT_INV
Arg0 Arg1
Arg0 := BLS12_381.gt_inv(Arg1) - Invert a GT-value
{tuple}
tuple
FATE_02
BLS12_381_GT_ADD
Arg0 Arg1 Arg2
Arg0 := BLS12_381.gt_add(Arg1, Arg2) - Add two GT-values
{tuple,tuple}
tuple
FATE_02
BLS12_381_GT_MUL
Arg0 Arg1 Arg2
Arg0 := BLS12_381.gt_mul(Arg1, Arg2) - Multiply two GT-values
{tuple,tuple}
tuple
FATE_02
BLS12_381_GT_POW
Arg0 Arg1 Arg2
Arg0 := BLS12_381.gt_pow(Arg1, Arg2) - Scalar exponentiation for a GT-value (Arg2), and an Fr-value
{tuple,tuple}
tuple
FATE_02
BLS12_381_GT_IS_ONE
Arg0 Arg1
Arg0 := BLS12_381.gt_is_one(Arg1) - Check if a GT value is "one"
{tuple}
bool
FATE_02
BLS12_381_PAIRING
Arg0 Arg1 Arg2
Arg0 := BLS12_381.pairing(Arg1, Arg2) - Find the pairing of a G1-value (Arg1) and a G2-value (Arg2)
{tuple,tuple}
tuple
FATE_02
BLS12_381_MILLER_LOOP
Arg0 Arg1 Arg2
Arg0 := BLS12_381.miller_loop(Arg1, Arg2) - Do the Miller-loop step of pairing for a G1-value (Arg1) and a G2-value (Arg2)
{tuple,tuple}
tuple
FATE_02
BLS12_381_FINAL_EXP
Arg0 Arg1
Arg0 := BLS12_381.final_exp(Arg1) - Do the final exponentiation in pairing
{tuple}
tuple
FATE_02
BLS12_381_INT_TO_FR
Arg0 Arg1
Arg0 := to_montgomery(Arg1) - Convert (Big)integer to Montgomery representation (32 bytes)
{tuple}
tuple
FATE_02
BLS12_381_INT_TO_FP
Arg0 Arg1
Arg0 := to_montgomery(Arg1) - Convert (Big)integer to Montgomery representation (48 bytes)
{tuple}
tuple
FATE_02
BLS12_381_FR_TO_INT
Arg0 Arg1
Arg0 := from_montgomery(Arg1) - Convert Montgomery representation (32 bytes) to integer
{tuple}
tuple
FATE_02
BLS12_381_FP_TO_INT
Arg0 Arg1
Arg0 := from_montgomery(Arg1) - Convert Montgomery representation (48 bytes) to integer
{tuple}
tuple
FATE_02
AENS_LOOKUP
Arg0 Arg1
Lookup the name of Arg0. Returns option(AENS.name)
{string}
variant
FATE_02
ORACLE_EXPIRY
Arg0 Arg1
Arg0 := expiry block for oracle Arg1
{oracle}
int
FATE_02
AUTH_TX
Arg0
If in GA authentication context return Some(Tx) otherwise None.
{}
variant
FATE_02
STR_TO_LIST
Arg0 Arg1
Arg0 := string converted to list of characters
{string}
list
FATE_02
STR_FROM_LIST
Arg0 Arg1
Arg0 := string converted from list of characters
{list}
string
FATE_02
STR_TO_UPPER
Arg0 Arg1
Arg0 := to_upper(string)
{string}
string
FATE_02
STR_TO_LOWER
Arg0 Arg1
Arg0 := to_lower(string)
{string}
string
FATE_02
CHAR_TO_INT
Arg0 Arg1
Arg0 := integer representation of UTF-8 character
{char}
int
FATE_02
CHAR_FROM_INT
Arg0 Arg1
Arg0 := Some(UTF-8 character) from integer if valid, None if not valid.
{int}
variant
FATE_02
CALL_PGR
Arg0 Identifier Arg2 Arg3 Arg4 Arg5 Arg6
Potentially protected remote call. Arg5 is protected flag, otherwise as CALL_GR.
{contract,string,typerep,typerep,integer,integer,bool}
variant
FATE_02
CREATE
Arg0 Arg1 Arg2
Deploys a contract with a bytecode Arg1 and value Arg3. The init
arguments should be placed on the stack and match the type in Arg2. Writes contract address to the top of the accumulator stack. If an account on the resulting address did exist before the call, the payable
flag will be updated.
{contract_bytearray,typerep,integer}
contract
FATE_02
CLONE
Arg0 Arg1 Arg2 Arg3
Clones the contract under Arg1 and deploys it with value of Arg3. The init
arguments should be placed on the stack and match the type in Arg2. Writes contract (or None
on fail when protected) to the top of the accumulator stack. Does not copy the existing contract's store – it will be initialized by a fresh call to the init
function. If an account on the resulting address did exist before the call, the payable
flag will be updated.
{contract,typerep,integer,bool}
any
FATE_02
CLONE_G
Arg0 Arg1 Arg2 Arg3 Arg4
Like CLONE
but additionally limits the gas of the init
call by Arg3
{contract,typerep,integer,integer,bool}
any
FATE_02
BYTECODE_HASH
Arg0 Arg1
Arg0 := hash of the deserialized contract's bytecode under address given in Arg1 (or None
on fail). Fails on AEVM contracts and contracts deployed before Iris.
{contract}
variant
FATE_02
FEE
Arg0
Arg0 := The fee for the current call tx.
{}
integer
FATE_02
ADDRESS_TO_BYTES
Arg0 Arg1
Arg0 := the fixed size byte representation of the address Arg1
{address}
bytes
FATE_03
POSEIDON
Arg0 Arg1 Arg2
Arg0 := the Poseidon hash of Arg1 and Arg2 - all integers in the BLS12-381 scalar field
{integer, integer}
integer
FATE_03
MULMOD
Arg0 Arg1 Arg2 Arg3
Arg0 := (Arg1 * Arg2) mod Arg3
{integer, integer, integer}
integer
FATE_03
BAND
Arg0 Arg1 Arg2
Arg0 := Arg1 & Arg2
{integer, integer}
integer
FATE_03
BOR
Arg0 Arg1 Arg2
Arg0 := Arg1
Arg2
{integer, integer}
integer
BXOR
Arg0 Arg1 Arg2
Arg0 := Arg1 ^ Arg2
{integer, integer}
integer
FATE_03
BNOT
Arg0 Arg1
Arg0 := ~Arg1
{integer}
integer
FATE_03
BSL
Arg0 Arg1 Arg2
Arg0 := Arg1 << Arg2
{integer, integer}
integer
FATE_03
BSR
Arg0 Arg1 Arg2
Arg0 := Arg1 >> Arg2
{integer, integer}
integer
FATE_03
BYTES_SPLIT_ANY
Arg0 Arg1 Arg2
Arg0 := bytes_split_any(Arg1, Arg2), where a positive Arg2 is the length of the first chunk, and a negative Arg2 is the length of the second chunk. Returns None if byte array is not long enough.
{bytes, integer}
variant
FATE_03
BYTES_SIZE
Arg0 Arg1
Arg0 := bytes_size(Arg1), returns the number of bytes in the byte array.
{bytes}
integer
FATE_03
BYTES_TO_FIXED_SIZE
Arg0 Arg1 Arg2
Arg0 := bytes_to_fixe_size(Arg1, Arg2), returns Some(Arg1') if byte_size(Arg1) == Arg2, None otherwise. The type of Arg1' is bytes(Arg2) but the value is unchanged
{bytes, integer}
variant
FATE_03
INT_TO_BYTES
Arg0 Arg1 Arg2
Arg0 := turn integer Arg1 into a byte array (big endian) length Arg2 (truncating if not fit).
{integer, integer}
bytes
FATE_03
STR_TO_BYTES
Arg0 Arg1
Arg0 := turn string Arg1 into the corresponding byte array.
{string}
bytes
FATE_03
DEACTIVATE
Mark the current contract for deactivation.
{}
none
FATE_01
ABORT
Arg0
Abort execution (dont use all gas) with error message in Arg0.
{string}
none
FATE_01
EXIT
Arg0
Abort execution (use upp all gas) with error message in Arg0.
{string}
none
FATE_01
NOP
The no op. does nothing.
{}
none
FATE_01
Opcodes, Flags and Gas
0x0
RETURN
true
true
true
10
0x1
RETURNR
true
true
true
10
0x2
CALL
true
true
true
10
0x3
CALL_R
true
false
true
100
0x4
CALL_T
true
true
true
10
0x5
CALL_GR
true
false
true
100
0x6
JUMP
true
true
true
10
0x7
JUMPIF
true
true
true
10
0x8
SWITCH_V2
true
true
true
10
0x9
SWITCH_V3
true
true
true
10
0xa
SWITCH_VN
true
true
true
10
0xb
CALL_VALUE
false
true
true
10
0xc
PUSH
false
true
true
10
0xd
DUPA
false
true
true
10
0xe
DUP
false
true
true
10
0xf
POP
false
true
true
10
0x10
INCA
false
true
true
10
0x11
INC
false
true
true
10
0x12
DECA
false
true
true
10
0x13
DEC
false
true
true
10
0x14
ADD
false
true
true
10
0x15
SUB
false
true
true
10
0x16
MUL
false
true
true
10
0x17
DIV
false
true
true
10
0x18
MOD
false
true
true
10
0x19
POW
false
true
true
10
0x1a
STORE
false
true
true
10
0x1b
SHA3
false
true
true
100
0x1c
SHA256
false
true
true
100
0x1d
BLAKE2B
false
true
true
100
0x1e
LT
false
true
true
10
0x1f
GT
false
true
true
10
0x20
EQ
false
true
true
10
0x21
ELT
false
true
true
10
0x22
EGT
false
true
true
10
0x23
NEQ
false
true
true
10
0x24
AND
false
true
true
10
0x25
OR
false
true
true
10
0x26
NOT
false
true
true
10
0x27
TUPLE
false
true
true
10
0x28
ELEMENT
false
true
true
10
0x29
SETELEMENT
false
true
true
10
0x2a
MAP_EMPTY
false
true
true
10
0x2b
MAP_LOOKUP
false
true
true
10
0x2c
MAP_LOOKUPD
false
true
true
10
0x2d
MAP_UPDATE
false
true
true
10
0x2e
MAP_DELETE
false
true
true
10
0x2f
MAP_MEMBER
false
true
true
10
0x30
MAP_FROM_LIST
false
true
true
10
0x31
MAP_SIZE
false
true
true
10
0x32
MAP_TO_LIST
false
true
true
10
0x33
IS_NIL
false
true
true
10
0x34
CONS
false
true
true
10
0x35
HD
false
true
true
10
0x36
TL
false
true
true
10
0x37
LENGTH
false
true
true
10
0x38
NIL
false
true
true
10
0x39
APPEND
false
true
true
10
0x3a
STR_JOIN
false
true
true
10
0x3b
INT_TO_STR
false
true
true
100
0x3c
ADDR_TO_STR
false
true
true
100
0x3d
STR_REVERSE
false
true
true
100
0x3e
STR_LENGTH
false
true
true
10
0x3f
BYTES_TO_INT
false
true
true
10
0x40
BYTES_TO_STR
false
true
true
100
0x41
BYTES_CONCAT
false
true
true
10
0x42
BYTES_SPLIT
false
true
true
10
0x43
INT_TO_ADDR
false
true
true
10
0x44
VARIANT
false
true
true
10
0x45
VARIANT_TEST
false
true
true
10
0x46
VARIANT_ELEMENT
false
true
true
10
0x47
BITS_NONEA
false
true
true
10
0x48
BITS_NONE
false
true
true
10
0x49
BITS_ALLA
false
true
true
10
0x4a
BITS_ALL
false
true
true
10
0x4b
BITS_ALL_N
false
true
true
10
0x4c
BITS_SET
false
true
true
10
0x4d
BITS_CLEAR
false
true
true
10
0x4e
BITS_TEST
false
true
true
10
0x4f
BITS_SUM
false
true
true
10
0x50
BITS_OR
false
true
true
10
0x51
BITS_AND
false
true
true
10
0x52
BITS_DIFF
false
true
true
10
0x53
BALANCE
false
true
true
10
0x54
ORIGIN
false
true
true
10
0x55
CALLER
false
true
true
10
0x56
BLOCKHASH
false
true
true
1000 (iris), 10 (lima)
0x57
BENEFICIARY
false
true
true
10
0x58
TIMESTAMP
false
true
true
10
0x59
GENERATION
false
true
true
10
0x5a
MICROBLOCK
false
true
true
10
0x5b
DIFFICULTY
false
true
true
10
0x5c
GASLIMIT
false
true
true
10
0x5d
GAS
false
true
true
10
0x5e
ADDRESS
false
true
true
10
0x5f
GASPRICE
false
true
true
10
0x60
LOG0
false
true
true
1000
0x61
LOG1
false
true
true
1100
0x62
LOG2
false
true
true
1200
0x63
LOG3
false
true
true
1300
0x64
LOG4
false
true
true
1400
0x65
SPEND
false
false
true
5000 (iris), 100 (lima)
0x66
ORACLE_REGISTER
false
false
false
10000 (iris), 100 (lima)
0x67
ORACLE_QUERY
false
false
false
10000 (iris), 100 (lima)
0x68
ORACLE_RESPOND
false
false
false
10000 (iris), 100 (lima)
0x69
ORACLE_EXTEND
false
false
false
10000 (iris), 100 (lima)
0x6a
ORACLE_GET_ANSWER
false
false
true
2000 (iris), 100 (lima)
0x6b
ORACLE_GET_QUESTION
false
false
true
2000 (iris), 100 (lima)
0x6c
ORACLE_QUERY_FEE
false
false
true
2000 (iris), 100 (lima)
0x6d
AENS_RESOLVE
false
false
true
2000 (iris), 100 (lima)
0x6e
AENS_PRECLAIM
false
false
false
10000 (iris), 100 (lima)
0x6f
AENS_CLAIM
false
false
false
10000 (iris), 100 (lima)
0x70
AENS_UPDATE
false
false
false
10000 (iris), 100 (lima)
0x71
AENS_TRANSFER
false
false
false
10000 (iris), 100 (lima)
0x72
AENS_REVOKE
false
false
false
10000 (iris), 100 (lima)
0x73
BALANCE_OTHER
false
true
true
2000 (iris), 50 (lima)
0x74
VERIFY_SIG
false
true
true
1300
0x75
VERIFY_SIG_SECP256K1
false
true
true
1300
0x76
CONTRACT_TO_ADDRESS
false
true
true
10
0x77
AUTH_TX_HASH
false
true
true
10
0x78
ORACLE_CHECK
false
false
true
100
0x79
ORACLE_CHECK_QUERY
false
false
true
100
0x7a
IS_ORACLE
false
false
true
100
0x7b
IS_CONTRACT
false
false
true
100
0x7c
IS_PAYABLE
false
false
true
100
0x7d
CREATOR
false
true
true
10
0x7e
ECVERIFY_SECP256K1
false
true
true
1300
0x7f
ECRECOVER_SECP256K1
false
true
true
1300
0x80
ADDRESS_TO_CONTRACT
false
true
true
10
0x81
BLS12_381_G1_NEG
false
true
true
100
0x82
BLS12_381_G1_NORM
false
true
true
100
0x83
BLS12_381_G1_VALID
false
true
true
2000
0x84
BLS12_381_G1_IS_ZERO
false
true
true
30
0x85
BLS12_381_G1_ADD
false
true
true
100
0x86
BLS12_381_G1_MUL
false
true
true
1000
0x87
BLS12_381_G2_NEG
false
true
true
100
0x88
BLS12_381_G2_NORM
false
true
true
100
0x89
BLS12_381_G2_VALID
false
true
true
2000
0x8a
BLS12_381_G2_IS_ZERO
false
true
true
30
0x8b
BLS12_381_G2_ADD
false
true
true
100
0x8c
BLS12_381_G2_MUL
false
true
true
1000
0x8d
BLS12_381_GT_INV
false
true
true
100
0x8e
BLS12_381_GT_ADD
false
true
true
100
0x8f
BLS12_381_GT_MUL
false
true
true
100
0x90
BLS12_381_GT_POW
false
true
true
2000
0x91
BLS12_381_GT_IS_ONE
false
true
true
30
0x92
BLS12_381_PAIRING
false
true
true
12000
0x93
BLS12_381_MILLER_LOOP
false
true
true
5000
0x94
BLS12_381_FINAL_EXP
false
true
true
7000
0x95
BLS12_381_INT_TO_FR
false
true
true
30
0x96
BLS12_381_INT_TO_FP
false
true
true
30
0x97
BLS12_381_FR_TO_INT
false
true
true
30
0x98
BLS12_381_FP_TO_INT
false
true
true
30
0x99
AENS_LOOKUP
false
false
true
2000
0x9a
ORACLE_EXPIRY
false
false
true
2000
0x9b
AUTH_TX
false
true
true
100
0x9c
STR_TO_LIST
false
true
true
100
0x9d
STR_FROM_LIST
false
true
true
100
0x9e
STR_TO_UPPER
false
true
true
100
0x9f
STR_TO_LOWER
false
true
true
100
0xa0
CHAR_TO_INT
false
true
true
10
0xa1
CHAR_FROM_INT
false
true
true
10
0xa2
CALL_PGR
true
false
true
100
0xa3
CREATE
true
false
true
10000
0xa4
CLONE
true
false
true
5000
0xa5
CLONE_G
true
false
true
5000
0xa6
BYTECODE_HASH
false
true
true
100
0xa7
FEE
false
true
true
10
0xa8
ADDRESS_TO_BYTES
false
true
true
10
0xa9
POSEIDON
false
true
true
6000
0xaa
MULMOD
false
true
true
10
0xab
BAND
false
true
true
10
0xac
BOR
false
true
true
10
0xad
BXOR
false
true
true
10
0xae
BNOT
false
true
true
10
0xaf
BSL
false
true
true
10
0xb0
BSR
false
true
true
10
0xb1
BYTES_SPLIT_ANY
false
true
true
10
0xb2
BYTES_SIZE
false
true
true
10
0xb3
BYTES_TO_FIXED_SIZE
false
true
true
10
0xb4
INT_TO_BYTES
false
true
true
10
0xb5
STR_TO_BYTES
false
true
true
10
0xfa
DEACTIVATE
false
true
true
10
0xfb
ABORT
true
true
true
10
0xfc
EXIT
true
true
true
10
0xfd
NOP
false
true
true
1
Gas
Each instruction uses the base gas as described in the table above. In addition to the instruction base cost (some) instructions also cost gas in relation to the memory they use. The base cost for memory is one gas per "cell" used. A cell is the memory word of an underlying machine which is defined to be a 64-bit word.
Each use of a a cell is counted and for each 1024 cells used the price is increased by 1. If a contract uses 1024 cells it will cost 1024 gas, if it uses 1025 cells it will cost 1026 gas. Using 2049 cells costs 3072 gas and so on.
When calculating the cell cost the total number of cells used after the instruction is used to determine the price for all new cells used by the instruction. So if you have used 1020 cells and then one instruction uses 5 new cells, then the gas cost for that instruction is 10 and not 6.
Each use of a stack slot (a push) costs gas in the same way and is also counted towards the number of used cells. Each pop of a stack slot does not cost gas and does not decrease the gas cost either but it reduced the count of number of cells in use.
The instructions uses cells in the following way.
ADD, SUB, MUL, DIV, MOD
After the operation is done the size of the absolute value of the result is calculated, and one cell is used per 64 bits that has a 1 set. Integers -18446744073709551615 to 18446744073709551615 uses 1 cell, and integers -340282366920938463463374607431768211456 to -18446744073709551616 and 18446744073709551616 to 340282366920938463463374607431768211456 uses 2 cells, and so on.
POW
The result of the pow instruction is computed recursively and for each step in the recursion the words used are calculated and the operation is aborted if all gas is used up. Given the function words which calculates the number of cells in an integer as described above (1 per 64 bits used). The number of cells are calculated as follows.
TUPLE
For creating a tuple you have already payed gas for the elements when you pushed them on the stack with other operations, then the new tuple increase the cell count by the size of the tuple plus 2.
Note that creating the tuple pops the elements from the stack so the cell count only increases by 2 by the make_tuple instruction, but the gas cost is the cost for size+2 cells.
Note also that when calculating cell cost the total number of cells used after the instruction is used to determine the price for all new cells used by the instruction.
SETELEMENT
The number of cells used is the tuple size + 2.
MAP_EMPTY
The cell cost is 2.
MAP_UPDATE
The cell cost is 2.
MAP_FROM_LIST
The cell cost is 2 + length of the list.
MAP_TO_LIST
The cell cost is 2 * length of the list.
CONS
The cell cost is 2.
APPEND
The cell cost is 2 * length of the first list.
STR_JOIN
The cell cost is 1 cell per 8 bytes in the joined string + 1 cell.
INT_TO_STR
The cell cost is 1 cell per 8 bytes in the produced string + 1 cell.
ADDR_TO_STR
The cell cost is 1 cell per 8 bytes in the produced string + 1 cell.
STR_REVERSE
The cell cost is 1 cell per 8 bytes in the produced string + 1 cell.
INT_TO_ADDR
The cell cost is 1 cell per 8 bytes in the produced address + 1 cell.
BITS_NONE, BITS_NONEA, BITS_ALL, BITS_ALLA
The cell cost is 1 cell.
BITS_ALL_N
The cell cost is 1 for every 64 bits used.
BITS_SET, BITS_CLEAR
The cell cost is 1 for every 64 bits used by the resulting bit field.
BYTES_CONCAT
The cell cost is 1 cell per 8 bytes in the produced byte array.
BYTES_TO_STR
The cell cost is 1 cell per 8 bytes in resulting string + 1 cell.
BYTES_SPLIT
The number of cells used is the tuple size which is 2 + 2.
AUTH_TX_HASH
If in auth context the number of cells used is 2 + 2, otherwise the number of cells used is 1 + 2.
VARIANT
The cell cost is two times the length of the list of arities plus one for each element in the variant plus four.
Appendix 1: FATE serialization
A more formal description of the serialization can be found in the general serialization document. Here we will try to describe the serialization more with words.
FATE code is serialized in three chunks:
Code: The code itself.
Symbols: An optional symbol table.
Annotations: Optional additional information.
Each chunk is an RLP encoding of a byte array that is the serialization of the chunk. They all have to be there in the serialization but they can be empty. An empty code chunk is just the RPL encoding of the empty byte array, i.e the byte 128. Symbols and Annotations can be empty but they have to be there as the RLP encoding of the RLP encoding of the empty map i.e. the bytes 130, 47, 0.
An empty FATE contract is encoded as the byte sequence 128, 130, 47, 0, 130, 47, 0.
Appendix 2: Delegation signatures
A couple of FATE operations can perform actions on behalf of a "user", these operations are: AENS_PRECLAIM
, AENS_CLAIM
, AENS_UPDATE
, AENS_TRANSFER
, AENS_REVOKE
, ORACLE_REGISTER
, ORACLE_RESPOND
, and ORACLE_EXTEND
. The first argument of these operations is a delegation signature - the signature "proves" that the user is allowed to manipulate the object (name or oracle). Naturally, if the contract itself is the owner of the name/oracle the signature is not needed. Otherwise, the user signs (using the private key) data authorizing the operation. Note: it is not possible to make a delegation signature using a generalized account.
There are five different delegation signatures:
AENS_PRECLAIM
- the user signs:owner account + contract
AENS_CLAIM
,AENS_UPDATE
,AENS_TRANSFER
,AENS_REVOKE
- the user signs:owner account + name hash + contract
AENS wildcard (valid for any name) - the user signs:
owner account + contract
[New inFATE_03
]ORACLE_REGISTER
,ORACLE_EXTEND
- the user signs:owner account + contract
ORACLE_RESPOND
- the user signs:query id + contract
To protect about cross network re-use of signatures, the data to be signed is also prefixed with the network id.
From Ceres: Serialized signature data
From Ceres/FATE_03
the material to be signed is more structured; the reason is two-fold, (a) to make it easier for the signer to see the what is signed and why, and (b) to safeguard against spoofing a transaction as a delegation signature (their structure was similar). Note: the semantic data to be signed has not changed from the description above, only the exact bytes to be signed and its structure.
For general information about serialization, RLP encoding, etc, see the general serialization document.
We use the tag 0x1a01
to identify delegation signatures. We use the following tags/types to identify the different delegation signatures:
1
aens wildcard
2
aens name
3
aens preclaim
4
oracle
5
oracle response
For serialization we use a schema similar to chain object serialization with the tags in the table above and version is 1. I.e. S = rlp([tag, vsn] ++ fields)
with fields as described below. The complete binary to sign is:
AENS Wildcard
AENS Name
AENS Preclaim
Oracle handling
Oracle response
Notation
Some notes on notation and definition of terms used in this document.
Bits
Bits are counted from the least significant bit, starting on 0. When bits are written out they are written from the most significant bit to the least significant bit.
Example the number 1 in a byte would be written in binary as:
And we would say that bit 0 is set to 1. All other bits 1 to 7 are set to 0.
Word size
The word size of the machine is 8 bits (one byte) but each type and instruction uses words of varying sizes, all multiples of bytes though.
Last updated