I recently contributed tests to across protocol’s smart contracts repository and in this blog I’ll explain how the protocol works, its architecture, and a bit about my contributions.
The Across Protocol and Relayer Mechanism
As blockchain technology evolves, the need for efficient cross-chain token transfers becomes increasingly important. Traditional bridging methods often involve long wait times, making the user experience suboptimal. Across Protocol addresses this issue by leveraging relayers, enabling instant cross-chain settlements.
What is a Relayer?
Relayers are entities or systems that facilitate instant token transfers between chains. Instead of waiting for the slow bridging process, relayers "front" tokens on the destination chain.
How does it work:
Fronting Tokens:
When users initiate a token transfer (e.g., 100 USDC from L2 to L1), they don’t need to wait for the long bridging time.
A relayer steps in to “front” the tokens on the destination chain (L1).
For example:
User on L2: “I want to send 100 USDC to L1.”
Relayer: “I’ll give you 100 USDC on L1 right now and collect your L2 USDC later.”
Making Transfers Faster: This mechanism ensures a seamless user experience with near-instant cross-chain transfers.
The Refund Process:
After fronting tokens on the destination chain, the relayer needs to be reimbursed. This is achieved through the following steps:
Token Collection: The relayer collects the user’s original tokens on L2 via the
executeRelayerRefundLeaf
function.Token Bridging: The
bridgeTokensToHubPool
function is used to send the collected tokens back to the HubPool on L1.
Complete Flow Overview:
User deposits tokens on L2 (World Chain).
Relayer fronts tokens to the user on L1.
Relayer claims original tokens on L2 using
executeRelayerRefundLeaf
.SpokePool uses
_bridgeTokensToHubPool
to send these tokens back to L1.
This mechanism significantly reduces the time users need to wait for their tokens to be available on the destination chain.
Across Protocol Architecture
The Across Protocol simplifies cross-chain token transfers by leveraging relayers and a hub-and-spoke architecture. Below is a detailed explanation of its workflow, inspired by the whitepaper:
General Workflow
Let’s say you want to move USDC from WorldChain (L2) to Ethereum (L1):
Initiating the Request: A user initiates a request to send funds from an L2 chain (e.g., World Chain) to L1 (Ethereum).
Deposit Identification: The protocol identifies the deposit on the source chain and calculates the liquidity provider fee.
Relay Decision: The protocol determines whether an Instant Relayer is available:
If yes, the Instant Relayer fronts the tokens to the user on L1.
If no, the transaction follows the Slow Relay path, waiting for the traditional bridging process.
Funds Transfer: Tokens are transferred to the user via the chosen relay method (instant or slow).
Refund and Bridging: The relayer is reimbursed, and tokens are bridged back to the destination HubPool on Ethereum.
Optimistic Oracle: Any disputes during the process are resolved by the Optimistic Oracle, ensuring honesty and transparency.
My contributions and the testing approach:
In the past 2 weeks, I created test cases for the WorldChain SpokePool and other chain-specific spokepools.
Most of the other spokepools contracts were pretty straightforward. So I will explain the worldchain SpokePool contracts and the fundamentals behind writing the test, which will be helpful to writing any other tests for all other SpokePools.
Writing tests for WorldChain Spoke Pool:
The WorldChain Spoke Pool is a contract that bridges tokens between WorldChain (an L2 blockchain) and the Across Protocol's Hub Pool on L1. Unlike typical spoke pools, the WorldChain Spoke Pool uses a custom USDC bridge to transfer USDC tokens. This bridge is designed to be upgraded to support CCTP (Circle's Cross-Chain Transfer Protocol) in the future, allowing seamless USDC transfers.
My contribution involved writing comprehensive tests to ensure the functionality works seamlessly for different scenarios. Here's a step-by-step explanation of my approach, what I did, and why:
1. Understanding the Problem
The _bridgeTokensToHubPool
function in the Spoke Pool required logic to handle token bridging with the following conditions:
Custom USDC Bridge: When CCTP (Cross-Chain Transfer Protocol) was disabled, USDC needed to be bridged using a custom adapter (
IOpUSDCBridgeAdapter
).CCTP Integration: When CCTP was enabled, the system needed to switch to this protocol for bridging USDC tokens.
Standard Bridge for Non-USDC Tokens: Non-USDC tokens required compatibility with a fallback standard bridging mechanism.
The complexity stemmed from the USDC's unique upgrade path on WorldChain and the need to maintain backward compatibility with non-USDC tokens.
2. Implementation
a. Initialization Tests
Verified that the Spoke Pool was correctly set up with the appropriate constructor and proxy parameters.
Ensured that the
wrappedNativeToken
,usdcToken
, andcctpTokenMessenger
addresses were assigned properly, along with critical values like thecrossDomainAdmin
.
b. Token Bridging Tests
USDC Bridge Without CCTP
Confirmed that the USDC bridge adapter was used and its
sendMessage
method was called with the correct parameters.Ensured that the
allowance
for the USDC bridge matched the expected amount.
USDC Bridge With CCTP
Verified that the CCTP logic took precedence when enabled, and the
allowance
for the CCTP token messenger was updated correctly.Confirmed that the USDC bridge adapter was bypassed.
Standard Bridge for Non-USDC Tokens
- Tested the fallback mechanism for non-USDC tokens to ensure compatibility with the standard bridge.
c. Error Handling
- Simulated invalid reinitialization attempts and ensured that they reverted as expected, maintaining the contract's integrity.
d. Real-World Scenario Simulation
Created realistic relayer refund scenarios by constructing Merkle trees and verifying proof validations.
Used the
constructSingleRelayerRefundTree
utility function to simulate efficient and accurate tree structures.Simulated cross-domain message sending using a fake cross-domain messenger.
3. Why I Wrote the Tests This Way
Precision: Each branch of the token bridging logic (USDC, CCTP, and standard bridging) was independently tested to ensure accuracy.
Realism: Simulated real-world scenarios like relayer refunds and cross-domain messaging for practical reliability.
Error Prevention: Reinitialization tests ensured the contract’s UUPS proxy upgradeability feature didn’t introduce accidental bugs.
Clarity: Breaking the tests into clear scenarios made debugging faster and easier. By covering all these aspects, I ensured that the WorldChain Spoke Pool's functionality was robust, reliable, and ready for real-world deployment.
You can view all of my contributions here.
Final Thoughts
Across Protocol is tackling a major pain point in the blockchain space—long wait times for cross-chain transfers. With its innovative relayer mechanism and robust architecture, it’s setting a high standard for efficiency and user experience.
From testing the WorldChain SpokePool’s custom bridging logic to simulating real-world scenarios, contributing to this protocol has been an awesome experience. If you’re into blockchain development or just curious about how cross-chain systems work, I hope this blog gave you some valuable insights.
Catch you in the next one!