AcrossBridgeAdapterLib
Title: AcrossBridgeAdapterLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from Across (https://github.com/across-protocol/contracts)
Logic + ERC-7201 storage for the Across v3 intent/optimistic token-bridge adapter. Outbound
deposit pulls exactly inputAmount from the caller, force-approves the SpokePool for exactly that
amount, escrows the deposit intent, then resets the allowance to 0. Inbound handleV3AcrossMessage
is authenticated to the SpokePool and ONLY emits (no handler registry in v1 — the diamond itself is
the recipient and other facets manage the received funds).
TRUST MODEL: Across is an INTENT bridge — a relayer fronts outputToken on the destination at fill
time and is later reimbursed via UMA optimistic settlement. There is NO guaranteed fill: an unfilled
deposit past fillDeadline is refunded ON THIS CHAIN to the deposit's depositor, which is why the
adapter ALWAYS passes depositor = msg.sender (see deposit). Inbound fills are relayer-pushed and
optimistic — NOT yet UMA-finalized when handleV3AcrossMessage runs — so received funds/messages are
reversible-until-finalized and are never routed into OpenBridge (no M-of-N, no receiveId). Across
chain ids are passed raw by callers (no domain table, no admin surface). Reuses the shared
safe-transfer / force-approve helpers (BridgeFungibleLib.pullExact, AdapterBaseLib.forceApprove);
no bespoke ERC-20 plumbing.
Functions
acrossBridgeAdapterStorage
function acrossBridgeAdapterStorage() internal pure returns (AcrossBridgeAdapterStorage storage $);Returns
| Name | Type | Description |
|---|---|---|
| $ | AcrossBridgeAdapterStorage |
__AcrossBridgeAdapter_init
Configures the local SpokePool and registers the IAcrossBridgeAdapter ERC-165 id.
Reverts AcrossZeroAddress if spokePool_ is zero (so an unconfigured module cannot exist).
Called inside the diamond initializing window.
function __AcrossBridgeAdapter_init(address spokePool_) internal;Parameters
| Name | Type | Description |
|---|---|---|
| spokePool_ | address |
registerInterface
Writes true to the ERC-165 map slot for IAcrossBridgeAdapter.
function registerInterface() internal;spokePool
function spokePool() internal view returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
deposit
Escrows params.inputAmount of params.inputToken (pulled from msg.sender) as an Across v3
deposit intent toward the ERC-7930 params.recipient on params.destinationChainId. Strict CEI
under the reentrancy guard: checks, pull exactly inputAmount, approve the SpokePool for exactly
inputAmount, deposit, then reset the allowance to 0.
REFUND SAFETY (fund-safety critical): the SpokePool depositor field is who Across refunds ON THIS
CHAIN when the deposit expires unfilled, and the only party able to speed up the deposit. It is
ALWAYS msg.sender (the calling user) and NEVER address(this) — depositor = address(this) would
strand every expired-deposit refund in the diamond.
DESTINATION CROSS-CHECK (fail-closed, mirrors the ZetaChain SourceChainMismatch precedent): when
the ERC-7930 recipient's chainType is eip-155 (0x0000), its chain reference must equal
params.destinationChainId, else AcrossDestinationMismatch. For non-EVM chainTypes no cross-check
is possible (Across uses its own numeric ids for non-EVM chains) — the recipient bytes32 and
destinationChainId are then trusted as caller-supplied.
NOT payable: ERC-20 inputs only in v1 (msg.value == 0 is implicit — the SpokePool reverts on
non-zero value for non-wrapped-native inputs; native ETH users wrap first). No leftover sweep is
needed: the SpokePool pulls exactly inputAmount and the approve reset guarantees zero standing
allowance.
function deposit(IAcrossBridgeAdapter.DepositParams calldata params) internal;Parameters
| Name | Type | Description |
|---|---|---|
| params | IAcrossBridgeAdapter.DepositParams |
_parseAndCheckRecipient
Parses the ERC-7930 recipient (canonical widths enforced; reverts on empty/oversized/short-EVM
address fields) and fail-closed cross-checks a declared eip-155 chain reference against the raw
Across destinationChainId (reverts AcrossDestinationMismatch — see the deposit dev notes).
function _parseAndCheckRecipient(bytes calldata recipientBytes, uint256 destinationChainId)
private
pure
returns (bytes32 recipient);Parameters
| Name | Type | Description |
|---|---|---|
| recipientBytes | bytes | |
| destinationChainId | uint256 |
Returns
| Name | Type | Description |
|---|---|---|
| recipient | bytes32 |
_callSpokePool
The 12-arg SpokePool call lives in its own frame with the pool re-read from storage and message
copied to memory (a 1-slot value instead of a 2-slot calldata slice) — both are stack-too-deep
relief for deposit under the legacy codegen pipeline.
function _callSpokePool(bytes32 recipient, IAcrossBridgeAdapter.DepositParams calldata params) private;Parameters
| Name | Type | Description |
|---|---|---|
| recipient | bytes32 | |
| params | IAcrossBridgeAdapter.DepositParams |
handleV3AcrossMessage
SpokePool-authenticated fill-time delivery hook: reverts AcrossNotSpokePool unless
msg.sender is the configured SpokePool, then emits AcrossMessageReceived. NOTHING else in v1
— no handler registry (the diamond itself is the recipient; other facets manage received funds).
OPTIMISTIC: fills are relayer-pushed and NOT yet UMA-finalized when this is called — treat the
received funds/message as reversible-until-finalized. Never routed into OpenBridge (no M-of-N
confirmation, no receiveId).
function handleV3AcrossMessage(address tokenSent, uint256 amount, address relayer, bytes calldata message)
internal;Parameters
| Name | Type | Description |
|---|---|---|
| tokenSent | address | |
| amount | uint256 | |
| relayer | address | |
| message | bytes |
_chainIdFromReference
Right-aligns an ERC-7930 chain-reference (<= 32 bytes, big-endian) into a uint256 chainId.
For eip-155 chains the reference IS the chainId. Reverts AcrossChainReferenceTooLong if > 32 bytes.
function _chainIdFromReference(bytes memory ref) private pure returns (uint256 chainId);Parameters
| Name | Type | Description |
|---|---|---|
| ref | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| chainId | uint256 |