bridgeAndCall() on the AggLayer Enables a Superior User Experience: A Deep Dive

Shared state and unified liquidity mean developers can grow projects with seamless cross-chain transactions in an aggregated network—and UX that feels like a single chain

Polygon Labs
August 6, 2024
Aggregation
Image source: Dribbble

Building on the AggLayer comes with enormous benefits. Near the top? 

Developers can create a superior user experience with the bridgeAndCall() capabilities.

Here’s a simple way to think about it: Smart contracts in the AggLayer = bridgeAndCall(). It enables streamlined composability and interoperability across a web of sovereign chains—the AggLayer. 

In doing so, bridgeAndCall() unlocks the ability for developers to abstract away the cumbersome feeling of a multichain ecosystem. This is an important kind of chain abstraction: users won't need to know what chain they're on, because bridgeAndCall() takes care of all that in the back-end. All that will matter is the experience of using an application.

And as the AggLayer improves, these cross-chain transactions will become faster and cheaper, which will make bridgeAndCall() even more useful. Not only will devs be able to tap into the aggregated user bases and unified liquidity of every connected chain, but bridgeAndCall() opens up an entirely new design space. 

Think cross-chain applications that will be able to happen with a single click. 

Developers will be able to leverage bridgeAndCall() in order to make the AggLayer feel more web-like, even as the pessimistic proof, a novel zero-knowledge (ZK) proof, cryptographically ensures the safety of cross-chain transactions. 

In the end state of the AggLayer, bridgeAndCall() helps free users from the weight of cumbersome bridging and gets the industry one step closer to UX that feels good.

It gives developers advanced tooling to create cross-chain applications and executions that, in any other network, are impossible. 

Already, L2 <> L2 transactions on the AggLayer are possible. Check out this demo from ETHCC:

NOTE: Just to clarify, bridgeAndCall() isn’t yet live—yet. This covers how it will work, in the coming months. For a description of how token bridging works in the current spec of the AggLayer, read more here.

High-level: What is bridgeAndCall()? 

Iykyk, but basically: It’s an extremely powerful library that allows developers to program cross-chain logic in smart contracts.

Let’s kick it off with a simple example. Suppose a user wants to do the following:

  1. transfer an asset from Chain A to Chain B; 
  2. swap for a new asset; 
  3. transfer the new asset from Chain B to a gaming chain;
  4. and mint a gaming NFT.

With bridgeAndCall(), this can happen in a single click. It’s all one transaction.

The reason this is possible is because bridgeAndCall() essentially marries two logics:

  • “bridging” an asset from one aggregated chain to another; and
  • “calling” or triggering a contract after the asset has arrived on the new chain

With these powers combined, developers can create complex, multi-chain computations and workflows that, in a different world, are simply unimaginable—or at the very most, would require the worst feeling of bridging combined with extremely unoptimized fees. 

bridgeAndCall() fixes UX: No need to sign multiple times or wait between transactions.

Simplicity, simply. 

bridgeAndCall() anatomy 

Let’s establish how the unified bridge works; then, you can get a sense of how bridgeAndCall() is built on the basic primitives for advanced functionality. 

Every chain that is “connected” to the AggLayer joins a unified bridge, i.e. a contract on Ethereum. 

You can imagine that, as more chains join, the chance increases for a prover to malfunction or for there to be a malicious chain that will try to drain the bridge. 

That’s why the bridge is protected by a novel zero-knowledge proof called the pessimistic proof. The tl;dr is that by taking a pessimistic view of the world and treating each connected chain suspiciously, the pessimistic proof actually ensures the safety of the entire unified bridge. 

So, the unified bridge is secured by ZK. 

The bridge contains two bridging primitives: 

  1. bridgeAsset, which bridges a token; and 
  2. bridgeMessage, which bridges arbitrary data.

bridgeAndCall() is a new construct, built atop these primitives, that extends traditional bridge calls by bundling these primitives together. 

From one chain to the next, developers are enabled to write smart contracts that send a token AND data to be executed. 

Allowing this bundling creates the conditions to program extremely complex logic—bridge from one chain, execute a function; then if executed properly, bridge to another chain to execute another function, and on and on.

(Theoretically, with infinite gas, you could create a bridgeAndCall() that never ends. Who’s going to ouroboros the AggLayer?!)

Below, take a look at the code. Note that the core logic of the desired flow is encoded in the calldata + target contract (the call address):

Where:

Walking through the transaction flow

The first thing to note is that bridgeAndCall() depends on the BridgeExtension, a contract tasked with implementing the logic of the bridgeAndCall function. 

Just like the unified bridge contract, BridgeExtension will live on any aggregated chain that opts-in, at the same address. 

So let’s go through a token flow, step-by-step, from sending an L2 <> L2 native transaction.

  1. Bridging the asset. All bridgeAndCall() executions are sandboxed, so the first thing that happens is a unique receiver address is calculated on the destination chain; then a call is made to bridgeAsset()
  2. Bridging the message. In addition to passing along calldata, some extra control fields are added, and then bridgeMessage() is called.
  3. Sending it. The transaction gets processed and propagates through the AggLayer to become a claimable bundle (asset + message) on the destination chain
  4. Asset claim. When claimAsset() is executed, the incoming asset is transferred to the sandboxed address; note that at this point that the address is “empty,” meaning it’s like an externally owned account address
  5. Message claim / do the “call” from bridgeAndCall. claimMessage() is executed. This means the message is unwrapped, and a special contract (called JumpPoint) is deployed to the sandbox address (!)
  6. Wrapping it up. The JumpPoint's constructor is called. It detects what asset was bridged (i.e. the asset that is in the address), and subsequently calls the callAddress with the callData. Now, whatever logic was encoded by the developer or application is executed. If there's any error, the assets are sent to the fallback address. The JumpPoint self-destructs, which means that the sandbox address gets cleaned up, like nothing was ever there.

At the end, if successful, callAddress+callData have been executed.

In everyday language: It worked! The app utilizing bridgeAndCall() has successfully delivered some cross-chain experience to a user, but without the usual hassle. 

This is all fairly technical, but yields extremely compelling real-world applications and use cases in an aggregated network. 

Chains can truly become specialized appchains, hyperfocused on their own use case, without having to direct limited resources to chasing other infrastructure like dexes, NFT marketplaces, lending protocols, and more—all of which will be easily accessible through aggregated chains and via bridgeAndCall(). 

Explore the bridgeAndCall() docs, and let us know what you think: This is being built in the open, and fine feedback is always encouraged. 

* * *

Tune into the blog and our social channels to keep up with updates about Polygon.

The future of Web3 is aggregated.

Website | Twitter | Forum | Telegram | Discord | Instagram | LinkedIn | Polygon Knowledge Layer

More from blogs