Contract reference
QuaiRelay
0x003D2EC4C1Ff5e98898fEa6C6D1AAaA48FaDc11A
— v2, Quai mainnet, Cyprus-1, deployed 2026-11-02. solc 0.8.20, EVM target paris. 674-byte
runtime, confirmed live via quai_getCode. Source:
github.com/IboTheSecond/quai-relay.
v1 0x0031B09e63592B713768761cdDACC603974c10bD
(2026-09-19, 600 bytes) is retired: same interface and event, but without the Qi-ledger check
below. Do not send through it.
Purpose. Forward exactly msg.value to a caller-supplied recipient, in the same transaction,
so a wallet that can call a contract but can't make a plain value transfer can still move its
QUAI out. It holds nothing between calls.
Function
function sendTo(address payable to) external payable;Forwards the attached QUAI to to. Reverts the whole transaction — nothing is sent, nothing is
kept — if any of these hold:
| Condition | Revert reason |
|---|---|
msg.value == 0 | "Zero amount" |
to == address(0) | "Zero recipient" |
to == address(this) | "Recipient is the relay" |
to is not a Cyprus-1 address (uint160(to) >> 152 != 0, i.e. first byte isn't 0x00) | "Recipient not Cyprus-1" |
to is a Qi-ledger address (second byte 0x80 or above; on Quai such a call would burn the whole gas limit) | "Recipient is a Qi address" |
the forwarded call to to fails (e.g. to is a contract with no payable fallback) | "Payout failed" |
There is deliberately no receive() function — a bare transfer sent directly to the relay
address (not through sendTo) reverts rather than being accepted and stranded.
Event
event Relayed(address indexed from, address indexed to, uint256 amount);Emitted once, after the forward succeeds. from is msg.sender (the caller, i.e. the wallet
that signed the transaction), to and amount are exactly what was requested and paid.
Selector
sendTo(address) → 0xe6d25245 (keccak-256 of the signature, asserted against the deployed
bytecode's dispatcher in the repo's tests — never hand-typed as trusted).
Trust model
There is nothing to trust beyond reading the ~30 lines of source, by construction:
- No owner, no admin. There is no privileged address anywhere in the contract — no
owner, noonlyOwner, no role that can change behavior. - No storage. The contract writes zero storage slots across its lifetime (asserted in
test/QuaiRelay.test.cjs). It cannot accumulate state that a future call could read or act on. - No upgrade path, no
selfdestruct. The deployed bytecode is final; it can never be swapped for different logic. - Never holds funds. The only payable path (
sendTo) forwards the value before returning, and reverts the whole transaction if the forward fails. The absence ofreceive()means a stray direct transfer bounces instead of getting stuck in a contract with no withdraw function. - The recipient is chosen by the caller, in the same call it pays into. Nothing is
remembered between transactions, and no other account's call can redirect a QUAI already in
flight — each
sendTois self-contained.
What it cannot protect you from: naming the wrong recipient. That's true of any transfer, and the contract has no way to distinguish a typo from an intended payment — it only refuses recipients that are provably lossy (zero address, itself, another zone, the Qi ledger).