What a delivery costs in gas, and who pays
This page gives the gas that one delivery of a Solidus status message costs on Ethereum Sepolia, Avalanche Fuji and Arc testnet, measured from receipts on 2026-10-08, and says who pays it.
What a delivery is
A delivery is one transaction that calls submit(message, signatures) on a destination mirror. The mirror checks the signatures, stores the status and moves its sequence number up by one, as how validators sign and the gateway delivers describes.
The measurement
One fetch of GET /v1/messages?limit=50 on 2026-10-08 gave the applied rows, and each deliveryTx receipt was read between 17:35 and 17:50 UTC. "Gas used" is the receipt's figure: it includes the 21,000 base charge and the calldata. This is one day's measurement, not an average.
| Chain | Kind | n | Min | Median | Max |
|---|---|---|---|---|---|
| Ethereum Sepolia | heartbeat | 11 | 81,149 | 81,197 | 81,197 |
| Avalanche Fuji | heartbeat | 12 | 65,661 | 65,685 | 65,697 |
| Arc testnet | heartbeat | 13 | 65,661 | 65,685 | 65,697 |
All 36 transactions succeeded. Solana devnet does not use EVM gas, so its 13 rows are left out. The rows are heartbeats. Solidus queues one for each chain about every 600 seconds: the queued times in these rows are 600.3 seconds apart at the median (34 gaps, from 599.5 to 600.7).
Inside a chain the figure barely moves. Subtract the 21,000 base charge and the calldata (4 gas per zero byte, 16 per other byte), and all 36 receipts leave one constant: 55,565 on Sepolia, 40,065 on Fuji and Arc. The spread in the table is only the zero bytes in the signatures.
Sepolia costs 15,500 more for the same calldata, and the cause is a change on Sepolia, not in the contract. The mirror's deployed code is 5,040 bytes on all three chains and differs in 9 bytes, in three places, with identical compiler metadata at the end (cast code, 2026-10-08). Ethereum's Glamsterdam fork activated on Sepolia on 2026-10-06 at 13:53:36 UTC, which is block 11856337, and it carries gas repricing (EIP-8007 lists EIP-2780, EIP-8037 and EIP-8038). The mirror's own receipts show the step. In the 4,000 blocks before that block, all 302 heartbeat deliveries cost between 65,661 and 65,697 gas, the Fuji and Arc range. In the 4,000 blocks from it, all 82 cost between 81,161 and 81,197. The last delivery before the fork cost 65,697 and the first after it cost 81,185. A local replay of one Sepolia delivery from after the fork, under the older rules (cast call --trace at the previous block), used 65,673 gas. An empty call with no data estimates 15,060 gas on Sepolia and 21,225 on Fuji and Arc, so the base cost moved too. The 15,500 was not split among the repriced items.
Why kinds differ
Every kind pays for the signature check and one write of the sequence number. A heartbeat then writes a two-slot record: the local replay lists three storage changes, slot 0 and slots 6 and 7. An issuer status writes the issuer flag. A credential status writes the four-slot export record and the issuer flag, and for an active export it also writes the pointer to the latest export. A message that writes more slots costs more, and creating a storage slot costs several times what overwriting one does.
Why signatures matter
Verification does two things per signature: one ecrecover and one storage read to confirm a known validator signed. The gateway sends exactly three of the four signatures the API serves, the three lowest signer addresses, and all 36 deliveries carry the same 420 bytes of calldata.
Adding the fourth signature to one delivery per chain raised the estimate by 7,642 gas on all three chains. Calldata is 1,048 of that. The replay shows 3,000 for each ecrecover, which leaves 3,594 for the storage read and the loop. If each delivered signature costs what the fourth does, the three cost about 22,900 gas: 35 percent of a Fuji or Arc heartbeat and 28 percent of a Sepolia one. The threshold is 3, so a fourth signature adds cost and no authority.
Who pays
The gateway's account pays, in each chain's native testnet currency. All 36 receipts carry one sender, 0xcff9Dc43b74d64070501dbFa37891053dB31DB0f, on Sepolia, Fuji and Arc. That account has no code on Sepolia, is not one of the four validators that validators() lists on all three mirrors, and is not the registry's owner, the timelock. The mirror has no owner() and never reads the caller, so the account holds no role. Anyone could submit the same bytes and pay instead, as what the mirror cannot do explains.
Reading is free. A cast call against the mirror is an eth_call: it needs no account and pays no gas. A contract that reads the mirror inside its own transaction pays for that read like any call, as read the mirror contract covers. The faq says a revocation needs no gas payment from the user, which fits the sender above.
See it in one command
RPC=https://ethereum-sepolia-rpc.publicnode.com
TX=$(curl -sL 'https://bridge.solidus.network/v1/messages?limit=20' \
| jq -r '[.messages[] | select(.chainKey=="sepolia" and .state=="applied")][0].deliveryTx')
cast receipt $TX gasUsed --rpc-url $RPC
# 81173
cast receipt $TX from --rpc-url $RPC
# 0xcff9Dc43b74d64070501dbFa37891053dB31DB0f
cast tx 0x0000000000000000000000000000000000000000000000000000000000000001 --rpc-url $RPC
# Error: tx not found: 0x0000000000000000000000000000000000000000000000000000000000000001
This output is for transaction 0x3ad0ac6c...4318 on 2026-10-08. A later row prints a nearby figure. The last command is the control: a hash that does not exist fails. Live health is on status, integration steps are on developers, and the routes are in the Bridge API reference.