A complete blockchain implementation featuring: - synord: Full node with GHOSTDAG consensus - explorer-web: Modern React blockchain explorer with 3D DAG visualization - CLI wallet and tools - Smart contract SDK and example contracts (DEX, NFT, token) - WASM crypto library for browser/mobile
330 lines
7.4 KiB
Markdown
330 lines
7.4 KiB
Markdown
# Synor VM Host Function ABI
|
|
|
|
This document describes the host functions available to Synor smart contracts.
|
|
|
|
## Overview
|
|
|
|
Synor contracts are WebAssembly modules that import host functions from the `env` module.
|
|
All functions use the WASM calling convention with i32/i64 parameters and return values.
|
|
|
|
## Storage Operations
|
|
|
|
### `synor_storage_read`
|
|
```
|
|
synor_storage_read(key_ptr: i32, out_ptr: i32) -> i32
|
|
```
|
|
Reads a value from contract storage.
|
|
|
|
- `key_ptr`: Pointer to a 32-byte storage key
|
|
- `out_ptr`: Pointer to output buffer (must be at least 4096 bytes)
|
|
- Returns: Length of data read, or -1 if key not found
|
|
|
|
**Gas Cost**: 200 gas per byte read
|
|
|
|
### `synor_storage_write`
|
|
```
|
|
synor_storage_write(key_ptr: i32, value_ptr: i32, value_len: i32) -> i32
|
|
```
|
|
Writes a value to contract storage.
|
|
|
|
- `key_ptr`: Pointer to a 32-byte storage key
|
|
- `value_ptr`: Pointer to value data
|
|
- `value_len`: Length of value data
|
|
- Returns: 0 on success, -1 if in static call
|
|
|
|
**Gas Cost**: 5000 gas per byte written
|
|
|
|
### `synor_storage_delete`
|
|
```
|
|
synor_storage_delete(key_ptr: i32) -> i32
|
|
```
|
|
Deletes a value from contract storage.
|
|
|
|
- `key_ptr`: Pointer to a 32-byte storage key
|
|
- Returns: 1 if key existed, 0 otherwise
|
|
|
|
**Gas Refund**: 15000 gas
|
|
|
|
## Context Information
|
|
|
|
### `synor_get_caller`
|
|
```
|
|
synor_get_caller(out_ptr: i32)
|
|
```
|
|
Gets the address that called this contract.
|
|
|
|
- `out_ptr`: Pointer to 34-byte output buffer
|
|
|
|
### `synor_get_address`
|
|
```
|
|
synor_get_address(out_ptr: i32)
|
|
```
|
|
Gets the contract's own address.
|
|
|
|
- `out_ptr`: Pointer to 34-byte output buffer
|
|
|
|
### `synor_get_origin`
|
|
```
|
|
synor_get_origin(out_ptr: i32)
|
|
```
|
|
Gets the original transaction sender.
|
|
|
|
- `out_ptr`: Pointer to 34-byte output buffer
|
|
|
|
### `synor_get_value`
|
|
```
|
|
synor_get_value() -> i64
|
|
```
|
|
Gets the value (in sompi) sent with this call.
|
|
|
|
- Returns: Amount of sompi sent
|
|
|
|
### `synor_get_calldata_size`
|
|
```
|
|
synor_get_calldata_size() -> i32
|
|
```
|
|
Gets the size of the call data.
|
|
|
|
- Returns: Size in bytes
|
|
|
|
### `synor_get_calldata`
|
|
```
|
|
synor_get_calldata(out_ptr: i32, offset: i32, length: i32)
|
|
```
|
|
Copies call data to memory.
|
|
|
|
- `out_ptr`: Pointer to output buffer
|
|
- `offset`: Offset into call data
|
|
- `length`: Number of bytes to copy
|
|
|
|
### `synor_get_timestamp`
|
|
```
|
|
synor_get_timestamp() -> i64
|
|
```
|
|
Gets the current block timestamp.
|
|
|
|
- Returns: Unix timestamp in seconds
|
|
|
|
### `synor_get_block_height`
|
|
```
|
|
synor_get_block_height() -> i64
|
|
```
|
|
Gets the current block height (DAA score).
|
|
|
|
- Returns: Block height
|
|
|
|
### `synor_get_block_hash`
|
|
```
|
|
synor_get_block_hash(out_ptr: i32)
|
|
```
|
|
Gets the current block hash.
|
|
|
|
- `out_ptr`: Pointer to 32-byte output buffer
|
|
|
|
### `synor_get_gas_remaining`
|
|
```
|
|
synor_get_gas_remaining() -> i64
|
|
```
|
|
Gets the remaining gas for this execution.
|
|
|
|
- Returns: Remaining gas units
|
|
|
|
### `synor_get_chain_id`
|
|
```
|
|
synor_get_chain_id() -> i64
|
|
```
|
|
Gets the chain ID.
|
|
|
|
- Returns: Chain ID (0 = mainnet, 1 = testnet)
|
|
|
|
## Cryptographic Operations
|
|
|
|
### `synor_sha3`
|
|
```
|
|
synor_sha3(data_ptr: i32, data_len: i32, out_ptr: i32)
|
|
```
|
|
Computes SHA3-256 hash.
|
|
|
|
- `data_ptr`: Pointer to input data
|
|
- `data_len`: Length of input data
|
|
- `out_ptr`: Pointer to 32-byte output buffer
|
|
|
|
**Gas Cost**: 30 + 6 gas per byte
|
|
|
|
### `synor_blake3`
|
|
```
|
|
synor_blake3(data_ptr: i32, data_len: i32, out_ptr: i32)
|
|
```
|
|
Computes Blake3 hash.
|
|
|
|
- `data_ptr`: Pointer to input data
|
|
- `data_len`: Length of input data
|
|
- `out_ptr`: Pointer to 32-byte output buffer
|
|
|
|
**Gas Cost**: 30 + 6 gas per byte
|
|
|
|
### `synor_verify_ed25519`
|
|
```
|
|
synor_verify_ed25519(msg_ptr: i32, msg_len: i32, sig_ptr: i32, pk_ptr: i32) -> i32
|
|
```
|
|
Verifies an Ed25519 signature.
|
|
|
|
- `msg_ptr`: Pointer to message data
|
|
- `msg_len`: Length of message
|
|
- `sig_ptr`: Pointer to 64-byte signature
|
|
- `pk_ptr`: Pointer to 32-byte public key
|
|
- Returns: 1 if valid, 0 if invalid
|
|
|
|
**Gas Cost**: 3000 gas
|
|
|
|
## Events
|
|
|
|
### `synor_emit_log`
|
|
```
|
|
synor_emit_log(topics_ptr: i32, topics_count: i32, data_ptr: i32, data_len: i32) -> i32
|
|
```
|
|
Emits a log event.
|
|
|
|
- `topics_ptr`: Pointer to array of 32-byte topics
|
|
- `topics_count`: Number of topics (max 4)
|
|
- `data_ptr`: Pointer to event data
|
|
- `data_len`: Length of event data
|
|
- Returns: 0 on success, -1 if in static call
|
|
|
|
**Gas Cost**: 375 gas per topic + 8 gas per data byte
|
|
|
|
## Cross-Contract Calls
|
|
|
|
### `synor_call`
|
|
```
|
|
synor_call(addr_ptr: i32, value: i64, data_ptr: i32, data_len: i32, gas: i64) -> i32
|
|
```
|
|
Calls another contract.
|
|
|
|
- `addr_ptr`: Pointer to 32-byte contract address
|
|
- `value`: Amount of sompi to send
|
|
- `data_ptr`: Pointer to call data
|
|
- `data_len`: Length of call data
|
|
- `gas`: Gas limit for the call
|
|
- Returns: Length of return data, or negative error code
|
|
|
|
**Gas Cost**: 700 + 3 gas per data byte
|
|
|
|
### `synor_static_call`
|
|
```
|
|
synor_static_call(addr_ptr: i32, data_ptr: i32, data_len: i32, gas: i64) -> i32
|
|
```
|
|
Makes a read-only call to another contract.
|
|
|
|
- `addr_ptr`: Pointer to 32-byte contract address
|
|
- `data_ptr`: Pointer to call data
|
|
- `data_len`: Length of call data
|
|
- `gas`: Gas limit for the call
|
|
- Returns: Length of return data, or negative error code
|
|
|
|
### `synor_delegate_call`
|
|
```
|
|
synor_delegate_call(addr_ptr: i32, data_ptr: i32, data_len: i32, gas: i64) -> i32
|
|
```
|
|
Calls another contract in this contract's context.
|
|
|
|
- `addr_ptr`: Pointer to 32-byte contract address
|
|
- `data_ptr`: Pointer to call data
|
|
- `data_len`: Length of call data
|
|
- `gas`: Gas limit for the call
|
|
- Returns: Length of return data, or negative error code
|
|
|
|
### `synor_return_data_size`
|
|
```
|
|
synor_return_data_size() -> i32
|
|
```
|
|
Gets the size of return data from the last call.
|
|
|
|
- Returns: Size in bytes
|
|
|
|
### `synor_return_data_copy`
|
|
```
|
|
synor_return_data_copy(dest_ptr: i32, offset: i32, length: i32)
|
|
```
|
|
Copies return data from the last call.
|
|
|
|
- `dest_ptr`: Pointer to destination buffer
|
|
- `offset`: Offset into return data
|
|
- `length`: Number of bytes to copy
|
|
|
|
## Control Flow
|
|
|
|
### `synor_revert`
|
|
```
|
|
synor_revert(msg_ptr: i32, msg_len: i32)
|
|
```
|
|
Reverts execution with a message. Does not return.
|
|
|
|
- `msg_ptr`: Pointer to error message (UTF-8)
|
|
- `msg_len`: Length of error message
|
|
|
|
### `synor_return`
|
|
```
|
|
synor_return(data_ptr: i32, data_len: i32)
|
|
```
|
|
Sets return data for this call.
|
|
|
|
- `data_ptr`: Pointer to return data
|
|
- `data_len`: Length of return data
|
|
|
|
## Balance Operations
|
|
|
|
### `synor_get_balance`
|
|
```
|
|
synor_get_balance(addr_ptr: i32) -> i64
|
|
```
|
|
Gets the balance of an address.
|
|
|
|
- `addr_ptr`: Pointer to 34-byte address
|
|
- Returns: Balance in sompi
|
|
|
|
### `synor_transfer`
|
|
```
|
|
synor_transfer(addr_ptr: i32, amount: i64) -> i32
|
|
```
|
|
Transfers value to an address.
|
|
|
|
- `addr_ptr`: Pointer to 34-byte address
|
|
- `amount`: Amount of sompi to transfer
|
|
- Returns: 0 on success, -1 if in static call or insufficient balance
|
|
|
|
## Memory Layout
|
|
|
|
Contracts must export a `memory` of type WebAssembly.Memory. The minimum memory
|
|
size is 1 page (64 KB), maximum is 256 pages (16 MB).
|
|
|
|
## Contract Exports
|
|
|
|
Contracts must export the following functions:
|
|
|
|
```
|
|
__synor_init(params_ptr: i32, params_len: i32) -> i32
|
|
```
|
|
Called when the contract is deployed. Returns 0 on success, negative on error.
|
|
|
|
```
|
|
__synor_call(args_ptr: i32, args_len: i32) -> i32
|
|
```
|
|
Called for all subsequent interactions. The first 4 bytes of args are the
|
|
method selector. Returns length of return data, or negative on error.
|
|
|
|
## Method Selectors
|
|
|
|
Method selectors are computed as the first 4 bytes of the Blake3 hash of the
|
|
method name:
|
|
|
|
```rust
|
|
fn method_selector(name: &str) -> [u8; 4] {
|
|
let hash = blake3::hash(name.as_bytes());
|
|
[hash[0], hash[1], hash[2], hash[3]]
|
|
}
|
|
```
|
|
|
|
## Serialization
|
|
|
|
Arguments and return values are serialized using [Borsh](https://borsh.io/) encoding.
|