ZetaChainGatewayAdapterLib
Title: ZetaChainGatewayAdapterLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from ZetaChain (https://github.com/zeta-chain/protocol-contracts)
Logic + ERC-7201 storage for the ZetaChain GatewayEVM ERC-7786 gateway adapter. sendMessage builds
the ERC-7930 envelope and dispatches it via gateway.call to the destination's ZEVM universal app
(the hub), forwarding msg.value as the native messaging fee; onCall is the gateway-invoked delivery
hook that authenticates the source out-of-band via the reverse app⇒chainId map, de-duplicates per
(source, id), and delivers to the ERC-7930 recipient. EVM chains only.
HUB-ROUTED: a "remote" is the ZEVM UNIVERSAL APP for a hub chainId, not a direct peer adapter. Both a
forward (chainId => app) and a reverse (app => chainId) map are kept because inbound onCall only
exposes context.sender = the app. INVERTED/HUB INBOUND AUTH: onCall's msg.sender is the GatewayEVM
(driven by the ZetaChain TSS/observer set), so trust is established by matching context.sender to a
registered app and recovering its source chainId. Wire message (envelope) =
abi.encode(senderInterop, recipientInterop, payload, nonce).
Functions
zetaChainGatewayAdapterStorage
function zetaChainGatewayAdapterStorage() internal pure returns (ZetaChainGatewayAdapterStorage storage $);Returns
| Name | Type | Description |
|---|---|---|
| $ | ZetaChainGatewayAdapterStorage |
__ZetaChainGatewayAdapter_init
Stores the gateway + default revert gas, registers the hub route in BOTH maps, and registers the gateway-source ERC-165 id.
function __ZetaChainGatewayAdapter_init(
address gateway_,
uint256 hubChainId,
address hubRemoteApp,
uint256 defaultOnRevertGasLimit_
) internal;Parameters
| Name | Type | Description |
|---|---|---|
| gateway_ | address | The ZetaChain GatewayEVM (deployed contract, per-connected-chain address). |
| hubChainId | uint256 | The hub chainId whose ZEVM universal app terminates the route. |
| hubRemoteApp | address | The trusted ZEVM universal app for hubChainId. |
| defaultOnRevertGasLimit_ | uint256 | The default onRevertGasLimit for per-message RevertOptions. |
registerInterface
Writes true to the SHARED IERC7786GatewaySource ERC-165 map slot (0x11967553 → ...). Same slot
the CCIP/LayerZero/OP/Axelar adapters register; a Diamond mounts at most one gateway.
function registerInterface() internal;gateway
function gateway() internal view returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
getRemoteApp
function getRemoteApp(uint256 chainId) internal view returns (address);Parameters
| Name | Type | Description |
|---|---|---|
| chainId | uint256 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
getChainIdForApp
function getChainIdForApp(address remoteApp) internal view returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| remoteApp | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
defaultOnRevertGasLimit
function defaultOnRevertGasLimit() internal view returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
supportsAttribute
No sendMessage attributes are supported: surfacing RevertOptions as a per-message ERC-7786
attribute is #77 open question #8 (DEFERRED) — an admin-configured default is used instead.
function supportsAttribute(bytes4) internal pure returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| _ | bytes4 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
setGateway
function setGateway(address gateway_) internal;Parameters
| Name | Type | Description |
|---|---|---|
| gateway_ | address |
registerRemote
function registerRemote(uint256 chainId, address remoteApp) internal;Parameters
| Name | Type | Description |
|---|---|---|
| chainId | uint256 | |
| remoteApp | address |
setDefaultOnRevertGasLimit
function setDefaultOnRevertGasLimit(uint256 onRevertGasLimit) internal;Parameters
| Name | Type | Description |
|---|---|---|
| onRevertGasLimit | uint256 |
_registerRemote
One-shot registration of a trusted remote ZEVM universal app for chainId in BOTH maps.
Rejects zero app; rejects a chainId already mapped OR an app already mapped (either direction).
function _registerRemote(ZetaChainGatewayAdapterStorage storage $, uint256 chainId, address remoteApp) private;Parameters
| Name | Type | Description |
|---|---|---|
| $ | ZetaChainGatewayAdapterStorage | |
| chainId | uint256 | |
| remoteApp | address |
sendMessage
ERC-7786 source. Parses the ERC-7930 recipient into (destChainId, target), resolves the
destination's trusted ZEVM universal app (the hub route terminus), wraps the ERC-7930 envelope with
a source-minted monotonic nonce, and dispatches it via gateway.call. Forwards msg.value as the
native messaging fee (there is NO on-chain quote or refund from the gateway). Returns the
globally-unique keccak256(abi.encode(block.chainid, nonce)) as the ERC-7786 sendId.
No attributes are supported — any attribute reverts UnsupportedAttribute. The RevertOptions are an
admin-configured default (revertAddress = msg.sender, callOnRevert = false); surfacing them
per-message is #77 open question #8 (DEFERRED). remote = forward[destChainId] is the ZEVM universal
app / hub-terminated route; an unset route reverts UnknownDestinationChain.
function sendMessage(bytes calldata recipient, bytes calldata payload, bytes[] calldata attributes)
internal
returns (bytes32);Parameters
| Name | Type | Description |
|---|---|---|
| recipient | bytes | |
| payload | bytes | |
| attributes | bytes[] |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes32 |
onCall
Gateway-invoked delivery hook (INVERTED/HUB AUTH). Authenticates: (1) msg.sender is the configured
GatewayEVM; (2) context.sender is a registered trusted ZEVM universal app, recovering the source
chainId from the reverse map. De-dups per (source, delivery id) marking BEFORE delivery (strict
CEI), then delivers to the ERC-7930 recipient after asserting it targets THIS chain. Returns empty
bytes.
The delivery id is derived from the authenticated source + the source-minted nonce (NOT envelope content), so two byte-identical-but-distinct messages get distinct ids (neither dropped).
function onCall(MessageContext calldata context, bytes calldata message) internal returns (bytes memory);Parameters
| Name | Type | Description |
|---|---|---|
| context | MessageContext | |
| message | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bytes |