# 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.
