The Æternity Ethereum Virtual Machine (AEVM)
The AEVM is a version of the EVM: https://github.com/ethereum/yellowpaper
The AEVM can be emulated inside the Æternity node and no marshaling of arguments, code and data is necessary. This makes for fast upstart and faster execution of most smaller contracts.
There are a few differences between the EVM and the AEVM.
The AEVM provides an number of primitive operations that can be used to interact with the chain.
The SELFDESTRUCT instruction is not immediate, instead the contract is set in a disabled state where neither new contracts nor call transactions can call the contract directly. When all other contracts referring to a disabled contract are fully disabled the contract is disabled.
Æternity primitive operations
Interaction with the first class objects of the Æternity chain (e.g. oracles, names, and state channels) is done through calls to a built-in contract at address 0.
The value in the call indicates the tokens that the primop can use from the contract account. Unused tokens stay on the contract account.
The first argument in the call specifies which primop to call. The following arguments are encoded as Sophia data.
The total gas of the operation is a sum of the base gas and the op gas.
OpNo | Name | Value | Arguments | Return value | Base gas | Op gas |
---|---|---|---|---|---|---|
1 | Spend | Amount : int |
Recipient : address |
Nil |
12000 | 0 |
100 | Oracle register | (Unused.) | Acct : address, Sign : signature, QFee : int, TTL : Chain.ttl, QType : typerep, RType : typerep |
Oracle : address |
12000 | Proportional to oracle TTL argument TTL (interpreted as relative), specifically: ceiling(32000 * RelativeTTL / floor(60 * 24 * 365 / key_block_interval)) and the byte size of the transaction representing this operation, specifically: byte_size(OracleRegisterTx) * GasPerByte |
101 | Oracle query | QFee : int |
Oracle : address, Query : 'a, QTTL : Chain.ttl, RTTL : Chain.ttl |
Query : address |
12000 | Proportional to oracle query TTL argument QTTL (interpreted as relative), specifically: ceiling(32000 * RelativeTTL / floor(60 * 24 * 365 / key_block_interval)) and the byte size of the transaction representing this operation, specifically: byte_size(OracleQueryTx) * GasPerByte |
102 | Oracle respond | (Unused.) | Oracle : address, Query : address, Sign : signature, R : 'b |
() |
12000 | Proportional to oracle response TTL argument RTTL in oracle query (as found in the oracle query in the state, and interpreted as relative), specifically: ceiling(32000 * RelativeTTL / floor(60 * 24 * 365 / key_block_interval)) and the byte size of the transaction representing this operation, specifically: byte_size(OracleRespondTx) * GasPerByte |
103 | Oracle extend | (Unused.) | Oracle : address, Sign : signature, TTL : Chain.ttl |
() |
12000 | Proportional to oracle TTL argument TTL (interpreted as relative), specifically: ceiling(32000 * RelativeTTL / floor(60 * 24 * 365 / key_block_interval)) |
104 | Oracle get answer | (Unused.) | Oracle : address, Query : address |
option('b) |
12000 | 0 |
105 | Oracle get question | (Unused.) | Oracle : address, Query : address |
'a |
12000 | 0 |
106 | Oracle query fee | (Unused.) | Oracle : address |
int |
12000 | 0 |
200 | Name resolve | (Unused.) | Name : string, Key : string, Type : typerep |
option(address) |
12000 | 0 |
201 | Name preclaim | (Unused.) | Account : address, Commitment : hash, Sign : signature |
() |
12000 | Proportional to the byte size of the transaction representing this operation, specifically: byte_size(NamePreclaimTx) * GasPerByte |
202 | Name claim | (Unused.) | Account : address, Name : string, Salt : int, Sign : signature |
() |
12000 | Proportional to the byte size of the transaction representing this operation, specifically: byte_size(NameClaimTx) * GasPerByte |
203 | Name update | (Unused.) | TODO | TODO | TODO | TODO |
204 | Name transfer | (Unused.) | From : address, To : address, Hash : hash, Sign : signature |
() |
12000 | 0 |
205 | Name revoke | (Unused.) | Addr : address, Hash : hash, Sign : signature |
() |
12000 | 0 |
GasPerByte
is 20.
Note that the gas cost indicated in the table above does not include the gas required for the call instruction to the primop.
Calling state changing prim-ops in oracles and names's trees in off-chain
environment results in an error with output data not_allowed_off_chain
.
Chain specific instructions
The COINBASE instruction return the beneficiary of the current generation stored in the previous key block. When executing a contract in a state channel off-chain, COINBASE will return the beneficiary of the previous key block as seen by the participant executing the contract. In a forced progress call the COINBASE will return the current beneficiary.
The TIMESTAMP instruction returns the timestamp of the current micro block. When executing a contract in a state channel off-chain TIMESTAMP will return the timestamp of the last block as seen by the participant executing the contract. In a forced progress call the TIMESTAMP will return the timestamp of the current micro block.
The DIFFICULTY instruction returns the difficulty of the current generation stored in the previous key block. When executing a contract in a state channel off-chain DIFFICULTY will return the difficulty of the current generation stored in the last key block as seen by the participant executing the contract. In a forced progress call the DIFFICULTY will return the difficulty of the current generation.
The BLOCKHASH instruction returns the hash of the key block at the specified height. If the height is below genesis height the instruction returns 0. If the height is higher than or equal to the current height the instruction returns 0. If the height is lower than current height minus 256 the instruction returns 0. When executing a contract in a state channel (either off-chain or in a force progress) BLOCKHASH will return the hash of the key block at the specified heigh as seen by the one executing the contract.