Automated Transactions over RPC
Executing an automation task produces on-chain activity that nobody submitted. Supra exposes that activity through both RPC surfaces, so a client can observe a task running the same way it observes an ordinary transaction.
Two kinds of entry are involved:
| Entry | Produced by | Content |
|---|---|---|
| Automated transaction | An active task’s execution in a committed block | The call the task registered, with its logs and receipt |
| Automation record | The registry’s bookkeeping | Which tasks a cycle transition processed, or which task the runtime removed and why |
Automation records appear at cycle transitions, and also mid-cycle when the runtime removes a task — one that failed at runtime, or one that the EVM gas config of a new epoch no longer admits.
Which surface to use depends on the client. The Ethereum JSON-RPC API presents both as ordinary-looking transactions, which suits existing EVM tooling. The Supra REST API presents them as distinct typed objects with fields the Ethereum shape cannot carry, such as a task’s predicate and a record’s decoded action.
Ethereum JSON-RPC
Automated transactions and automation records are two of the four system
pseudo-transactions the Ethereum API serves. Their envelope, sentinel signature, from,
to, input and the supraTxKind field are described in
System pseudo-transactions:
an automated transaction carries "supraTxKind": "automated", an automation record
"automationRecord". For an automation record, to is the registry and input is the
ABI-encoded processTasks or removeRegisteredTask call it executed.
Beyond what that section covers:
hashis real. It is the entity’s own content hash, the same oneeth_getLogsandeth_getTransactionReceiptuse, not a hash of the envelope the API builds. Hashing the returned envelope yourself produces a different value.- The receipt does not carry
supraTxKind— only the transaction object does. A client that needs the kind fetches the transaction, not just the receipt. - An automated transaction’s
effectiveGasPriceis the gas unit price the node built the transaction at for that block. It is at most the task’sgasPriceCap; the registry does not schedule it. fromandnonceare the task owner and the task index.from,msg.senderandtx.originof the action are the task owner.nonceis the task index, and the owner’s account nonce is neither checked nor advanced, so(from, nonce)of an automated transaction overlaps the owner’s own nonce space. Separate automated from user transactions bysupraTxKindhere, or bytxn_typeon the REST API. An automation record’sfromis0x0000000000000000000000000000000053555000and itsgasPriceis 0.- An action that reverts, halts or is discarded is recorded as the transaction’s output, and the task stays registered. A predicate that fails at execution removes the task and produces an automation record; see How Automation Works.
Ordering within a block
eth_getBlockByNumber and eth_getBlockByHash list a block’s EVM transactions in this
order, in both hash-only and full-transaction modes:
- Block metadata
- Settlement credits
- Automation records
- User transactions
- Automated transactions
Logs
Logs emitted by block-metadata transactions, automated transactions and automation records
are queried through eth_getLogs, and the logs subscription, in the same way as the logs of
any EVM user transaction: the same filter fields apply, and each log carries its
pseudo-transaction’s hash and transactionIndex. The events a task’s action emits are logs of
its automated transaction.
The examples on this page use these shell variables. RPC_HOST is the RPC host, which the Supra
REST API paths below are appended to. RPC is a full JSON-RPC endpoint. The values here are
Devnet’s; its contract addresses are also listed in
Addresses on Devnet:
RPC_HOST=https://rpc-devnet.supra.com
RPC=$RPC_HOST/rpc/v1/eth
AUTOMATION_REGISTRY=0xa75a2cd8e61992526ed2eeaf1e1ab3b9ec472400
HASH="<transaction hash>"
HASH_1="<first transaction hash>"
HASH_2="<second transaction hash>"
HEIGHT="<block height>"There is no filter field that selects these transactions as such; filter by the emitting
contract’s address and the event’s topics. Filtering by a task’s target contract also returns
the logs of that contract’s other callers; to select a task’s executions, check
supraTxKind on each log’s transaction, or list a block’s automated transactions with
type=auto. For example, cycle transitions are followed by filtering the automation
registry’s AutomationCycleEvent, here over the last 1,000 blocks:
LATEST=$(cast block-number --rpc-url "$RPC")
curl -X POST "$RPC" -H 'Content-Type: application/json' -d '{
"jsonrpc": "2.0", "id": 1, "method": "eth_getLogs",
"params": [{
"fromBlock": "'"$(printf '0x%x' $((LATEST - 1000)))"'", "toBlock": "latest",
"address": "'"$AUTOMATION_REGISTRY"'",
"topics": ["'"$(cast keccak 'AutomationCycleEvent(uint64,uint8,uint64,uint64,uint8)')"'"]
}]
}'A node refuses an eth_getLogs request whose block range or result set exceeds its bound with
-32005, and the range can contain no cycle transition if it is shorter than a cycle; see
Error codes. To search further back, query in
ranges within the bound.
The event indexes the cycle index, the new state and the previous state, so those occupy
topics 1 to 3 and the start time and duration are in data. The registry’s other events
carry their task lists and amounts in data too; see
Events.
Supra REST API
The REST API carries fields the Ethereum shape cannot: a task’s predicate, the cycle a
record belongs to, and the record’s decoded action. Use v4, which is current. v3 has the
same discriminator and tag values, differing only in the nested output types; v4 adds
transaction inclusion proofs.
The transaction union
Every transaction the REST API returns is tagged with txn_type:
txn_type | Payload |
|---|---|
"user" | An ordinary submitted transaction |
"automated" | An automation task execution |
"block_metadata" | The block prologue |
"automation_record" | Registry bookkeeping |
"settlement" | A cross-VM settlement |
These are snake_case, unlike the camelCase values of supraTxKind on the Ethereum side.
By hash
curl "$RPC_HOST/rpc/v4/transactions/$HASH" -H 'Accept: application/json'One lookup resolves every kind: the endpoint tries user transactions, then automated transactions, block metadata, automation records and settlements, in that order. A client holding a hash from a block listing does not need to know which kind it has.
To resolve many hashes in one request:
curl -X POST "$RPC_HOST/rpc/v4/transactions/by_hashes" -H 'Content-Type: application/json' \
-d '{"hashes": ["'"$HASH_1"'", "'"$HASH_2"'"]}'The response has one entry per requested hash, in request order, with transaction null for
a hash that is not found. A response that would exceed the node’s size bound is cut short, and
the hashes it leaves out are listed in omitted for a follow-up request.
By block
curl "$RPC_HOST/rpc/v4/block/height/$HEIGHT?with_finalized_transactions=true" \
-H 'Accept: application/json'Narrow to one kind with type:
curl "$RPC_HOST/rpc/v4/block/height/$HEIGHT?with_finalized_transactions=true&type=auto"
curl "$RPC_HOST/rpc/v4/block/height/$HEIGHT?with_finalized_transactions=true&type=record"type | Selects |
|---|---|
auto | Automated transactions |
record | Automation records |
user | User transactions |
meta | Block metadata |
settlement | Settlement credits |
Execution order within a block covers both VMs: Move block metadata, EVM block metadata, Move settlement, EVM settlement credits, Move automation records, EVM automation records, user transactions in inclusion order, Move automated transactions, then EVM automated transactions.
By account
GET /rpc/v{3,4}/accounts/{address}/automated_transactions returns Move automated
transactions only: EVM automated transactions are not indexed by account. Find an EVM task’s
executions by block with type=auto, or by hash.
An automated transaction
The object carries the standard transaction fields plus predicate. This sample is
abridged: header also holds chain_id, expiration_timestamp and gas_unit_price, and
the object also has block_header, payload and, in v4, inclusion_proof. sender is an
object tagged with the VM, and sequence_number is the task index:
{
"txn_type": "automated",
"hash": "0x6a639921...",
"header": { "sender": { "Evm": "0x..." }, "sequence_number": 7, "max_gas_amount": 500000 },
"authenticator": { "Automation": "0xbed04a91..." },
"output": {
"Evm": {
"Success": {
"reason": "Stop",
"gas_used": 45205,
"gas_refunded": 0,
"logs": [],
"output": { "Call": "0x" }
}
}
},
"status": "Success",
"predicate": {
"type": "evm",
"kind": "contract_call",
"address": "0x2cd6f3c0f0ca46ea1616adf9e396ee99c24559df",
"input": "0x1f2a3b4c"
}
}predicate is present on every EVM automated transaction, since registering an EVM task
without one is rejected — see
How Automation Works. It records that SupraEVM
called address with input before executing the task and proceeded only because it
returned true. The field is absent on a Move automated transaction: Move automation
tasks do not carry predicates.
authenticator is how an automated transaction is identified structurally: it holds
Automation with the digest of the task’s registration transaction, rather than a
signature.
An automation record
This sample is abridged: the object also carries block_header, and output has the same
{"Evm": {"Success": ...}} shape as above.
{
"txn_type": "automation_record",
"hash": "0xeaf5df4d...",
"data": {
"record_index": 0,
"cycle_index": 16,
"block_height": 4211,
"action": { "Process": [1, 2, 5] }
},
"output": {},
"status": "Success"
}action is an externally tagged enum with two shapes:
| Shape | Meaning |
|---|---|
{"Process": [1, 2, 5]} | Those task indexes were processed at a cycle transition |
{"Remove": {"task_index": 7, "kind": "Error", "reason": "..."}} | The runtime removed task 7. reason describes why |
kind is "Error" for a task that failed at runtime, whose owner receives a partial refund,
or "GasConfigUpdate" for a task the EVM gas config of a new epoch no longer admits, whose
owner is refunded in full if it is a user task and nothing if it is a system task. See
Removal by the runtime.
The variant and kind names are PascalCase. Unlike the sibling types on this endpoint, these
enums carry no case conversion, so do not expect process, remove or error.
record_index is unique within a block, not globally. block_header is null when the
record is returned as part of a block, because the block is already the enclosing object.
Execution results for both kinds are the ordinary output and status fields. A record’s
output is always present; an automated transaction’s is optional in the schema and is
always present when returned inside a block.
Choosing a surface
| Goal | Use |
|---|---|
| Decode a task execution with existing EVM tooling | eth_getTransactionByHash, checking supraTxKind |
| React to task executions as they happen | eth_subscribe with supra_executedTransactions |
| Read the logs a task emitted | eth_getLogs filtered by the task’s target contract, then keep logs whose transaction is automated |
| See a task’s predicate, or why a task was removed | GET /rpc/v4/transactions/{hash} |
| Resolve every hash in a block listing at once | POST /rpc/v4/transactions/by_hashes |
| Find an EVM task’s executions | GET /rpc/v4/block/height/{height}?with_finalized_transactions=true&type=auto, keeping entries whose sender or payload is Evm |
Related
- How Automation Works — the execution model, task lifecycle, and why an automation record’s action is decoded the way it is.
- AutomationRegistry — registering the tasks these entries come from, and the events the registry emits.
- Differences from Ethereum — system pseudo-transactions, indices, subscriptions and the methods the Ethereum API does not serve.
- BlockMeta — the block-prologue execution behind the
blockMetadatakind. - The node’s API page, at
https://rpc-devnet.supra.com/docson Devnet — the shared transaction and block response shapes.