Send Tokens and Call Anything Cross Chain I John Nguyen
ETHGlobal·Tue, Dec 9, 2025, 12:00 AM
Join John Nguyen for a workshop titled "Send Tokens and Call Anything Cross Chain", featured at ETHGlobal Buenos Aires 2025! _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 🇦🇷 *ETHGlobal Buenos Aires* This workshop is specifically for ETHGlobal Buenos Aires, a 3-day hackathon held November 21-23 at the Centro de Convenciones Buenos Aires, bringing together the most skilled web3 developers, designers and product builders from all around the globe for a weekend-long adventure to advance the Ethereum ecosystem! Watch the full ETHGlobal New Delhi 2025 playlist here: https://www.youtube.com/playlist?list=PLXzKMXK2aHh76O7FfAHPJkZcqTIfYpoyf _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ✅ *Follow ETHGlobal* X: https://x.com/ETHGlobal Warpcast: https://warpcast.com/ethglobal Website: https://ethglobal.com YouTube: https://www.youtube.com/c/ETHGlobal _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Are you interested in Ethereum development and entrepreneurship?_ 👉 Sign up for the next ETHGlobal event: https://ethglobal.com/events 🎁 Get exclusive access and perks with ETHGlobal Plus! https://ethglobal.com/plus 📣 Want us to throw an event in your city? Tell us where! https://ethglobal.com/city
Transcript
[Music] Hello everybody. Thanks for tuning in. Thanks for coming. If you're on YouTube watching the live stream, thanks for coming. Um yeah, if there's any issues with like seeing my screen or hearing me or anything like that, please let me know.
Um I'm really bad with microphones generally. Um but yeah, today we're going to be talking about um in general layer zero, Stargate and the products that we offer and how we make the onchain space a little bit better. Uh but the general goal I want and the general message I want to convey in today's workshop is building omni chain composers. Um if uh this line already makes you wonder what that is, um stick till the end. Uh yeah, I'm I'm John.
I'm a developer relations engineer at layer zero labs. Um I'm 0x John on Twitter. If you've never seen me at layer zero before, it's because I just joined. Um so yeah, hopefully you'll enjoy this um workshop. So yeah, quickly about the agenda today, I'll just talk about how layer zero works.
Um the 101s of crosschain messaging. Um I'll talk about how Stargate works. um this idea of composability and as well as show you a simple example of a a composer um that I built um the other day. Also, there's a repo for it in the discord. So, if you're um if you see the partner-layer zero chat on e global discord, you can go there and there's a bunch of links in there that you can uh find useful.
Um so to start off uh layer zo as a global ledger or bridge infrastructure um if there's anything you want I want you to understand and to take away from this workshop are basically these three things. Layer zo as a bridge infrastructure is built upon three core principles. The first principle is permissionlessness right secondly it's censorship resistant and thirdly it's immutable. Um what is layer 0? So, layer 0 is essentially just a set of smart contracts um that we deploy to every chain that we support that your app can interact with um to send cross-chain messages.
Um so, at the core of it all, you're just sending a message from chain A to chain B um in a secure way. Um and you can build many applications on top of this core principle of message uh sending. And I'll go into it um a little bit deeper. Um so just again to zoom in um I'm going to go through a simple like work workflow of a message being sent from chain A to chain B. Um a little prerequisite to any sending um any message sending like that that will happen you need to configure your own security stack right so when a message flows from chain A to chain B there's some middleman that needs to um kind of verify that this message has not been tampered with.
So we call this the security stack or DVNs. DVNs stands for decentralized verifiable networks. Uh and the second thing you need to um set up is the executor. So the executor on the destination chain is the one actually delivering and calling the function calls on the destination to deliver your message. Um so if we start from the very very beginning, you have an app.
This is your app and you can send arbitrary data from your app on this on chain A to your app on chain B. And this data could be arbitrary messages or assets, tokens or even assets plus data um which is very useful for the concept of composing that we're going to go into a little bit deeper. But essentially your app interacts with the endpoint here right which is the interface for interacting and sending crosschain messages. After that the message is uh emitted from the from chain A and the security stack that we we've configured uh which consists of DVN that you pick yourself. So it could be Google Cloud, it could be layer zero.
Um if you want some middle chain like Axel or wormhole that also is supported. We currently have like 54 um I believe it's 54 DVNs that's supported. So you as the app developer can configure the amount of um DVNs that will verify the network which ones will be required and which one are optional. Um after that after each DVN independently verifies that the message or the payload has not been tempered with um the message will be sent to this contract called the message library on the destination chain. um and the executor that I mentioned previously will be the one calling the function to deliver that message through the endpoint to your app.
So going through this like send flow from the chain a from chain A then verifying this message and delivering it to chain B. Um, one important note about modular modular security stack that we kind of call is that historically as a developer when you're building a an app that needs to interact with another app on another chain um you're kind of left with two choices. you either go for really high security which consequently means that the cost of those of each independent transaction is very high or you choose something with lower security that's uh which means that the cost will be lower. So what layer zero allows you with modular security is that you can pick and choose your own security to your own taste. Um and essentially pick any point on the graph um which is like whether you want it to be secure or um if you want it to be super secure obviously your user would need to spend a little bit more on fees.
Um and then another neat feature about this is as our industry evolves we often times get new validation techniques. So new techniques to verify that our message hasn't been tampered with. Um in our case we you as the developer can simply modify the configuration to switch it to that new validation techniques. So for example polyhedra for zk proofs um or anything like that. Um I think the so this was basically the basics of what layer zero is.
It allows you to send messages. But to kind of build on top of that, one of the core primitives and the main use cases of um messaging is token transfers, right? Um sending assets from chain A to chain B. Um this is the core of any bridging, right? So if we look at the example of doing it for a single chain, so for example, you're sending from a user A to user B on one chain through the ERC20 contract.
All it is is like a central there's a central database or a mapping that you're updating. So you're update you're basically decreasing um the balance of user A and increasing the balance of user B right so that's simple enough um when you start to plug in like multiple chains and have something called omni chain transfers it suddenly becomes a little bit harder um now you have to kind of bookkeep and keep track of all these balances across multiple chains and uh yeah there's many many more function calls and state changes on both chains um so the way we do it is also using messaging right So imagine you have these like OFTs. So OFTs are omni omni chain fungeible tokens which essentially are extensions of ERC20 that allow you to your token to have um omni chain functionality. So on chain A you can imagine a earn function um that is being called on your underlying ERC20. a message is sent across chain to uh chain B and a mint function is called to kind of create those tokens again on chain B and uh essentially this is the basis of omni chain transfers but for you as a developer um in more practical terms we've built these standards um like I just mentioned the OFT standard for you to simply inherit from and use in your contracts if you want to um kind of use this technology so there's a couple standards that I want to go through quite of quickly.
So first is the standard O of contract, right? Um this one would allow you and you would generally use this if you're creating a token from scratch. So if you're issuing tokens from scratch kind of like layer zero with ZRO, Stargate with STG or shrapnel with shrap um you can use the OFT standard and kind of deploy those OFTs on different chains and have them uh essentially interact with each other on multiple chains. But if you're using a existing token, right, for example, USDC or something like that, you can um deploy something called an OFD adapter. So the OFD adapter essentially is uh a wrapper or an adapter around the existing token that would essentially lock on chain A and unlock on the other chain.
And again, those two chains and those two apps talk to each other um via the layer zero messaging protocol. Um so that is when you want to something like I mean it's called a lock box if you want to unlock and lock. On the other side there's also an a mint and burn adapter. This these is for the cases where you have um a and an an existing token um and that existing token gives you access to the mint and burn functions right and when you have access to the mint and burn functions you can essentially go and burn on one chain and mint on the other chain. So uh a few partners that have used mint and burn adapter areo for their usedy um PayPal for their pyusd and bitgo for WBTC.
Um also a few examples of adapters that the standard lockbox adapters being used. Um you might have heard of USDT0 issued by tether. Um Athena issued uh USD and SUSD um through OFT adapter as well as well as Ether. some of their kind of wrapped ethereum um tokens are also part of the OFT adapter standard. So what is Stargate and why I started kind of explaining layer zero and of uh well Stargate essentially plays a dual role in the layer 0 ecosystem.
So the first role is that it's a de facto front end the primary front end for all OFTs um in the layer zero ecosystem. That's the first thing. But secondly, what might interest you as the developer is that um Stargate is a liquidity provision protocol. So essentially they keep um they manage liquidity between multiple multiple chains for a lot of these um popular tokens that you use like USDC, USD, USDT or WET. Um and you can basically interact with Stargate contracts to send tokens from one chain to another.
And Stargate uses layer zero under the hood as well. Um so one thing to understand about Stargate before we go dive a little bit deeper um are this concepts of native chains or native pools and uh hydra. So essentially native chains are chains where a lot of these tokens like USDT and USDC are natively deployed. So the token issuers like tether and circle um they don't deploy on every chain obviously uh most native chains are the popular ones that you know like base and arbitum. So that's where Stargate have the Stargate pool contract, right?
There's also the hydra chains. So hydrochains are emerging chains kind of like monad or plasma or scroll where the token issuers like use like circle or tether didn't deploy and don't have deep liquidity yet but they still want to tap into this token and have their daps integrated. So uh that's what we call hydrochains. So for native chains again um there's a contract called Stargate pool right and essentially what it does it's it locks on chain A and then sends a Z message um through the endpoints and then unlocks on the other side quite simple it also keeps this like liquidity balance between using a um credit allocation system which is kind of interesting and then um the contract that is called the Stargate OFT is actually deployed on hydrochains. So for example, you want to send um USDC or USDT from Ethereum to any hydrochain like plasma, you would actually go through this uh flow.
You would call the Stargate pools contract on uh Ethereum and then a message would be sent to plasma for example and the Stargate Oft one to one backed representation on plasma essentially allowing these newer chains um to have like a onetoone backed liquidity pool of on the native chain which is kind of cool. Uh, one thing really important to note about both the Stargate OFT and the Stargate pool contracts is that all of them are actually OFTs. So, um, all of them inherit and implement the IO of interface. Which means if you know how to use and interact with regular OFTs, you inherently know how to use the target OFT contract and this target pool to send assets crosschain. Um, this leads us to a really neat kind of concept called composability.
So think about this um in terms of a hacker, a developer, right? You're going to be building something for this hackathon that is that has custom logic. Um likely it will have some exciting functionality or something like that, right? Just sending tokens from chain A to chain B. Well, in one case, it's pretty cool, but on another hand, it's kind of not that exciting.
So what makes this a little bit more cool um is this idea of composability. composability essentially what it allows you as a developer to do is to chain actions on the destination chain. So essentially um asking the question what what would I do after the my tokens are transferred on the destination chain for example you would want to supply it to a immediately uh for the user that would be just one click right um from the source chain um you want to supply to a you want to swap it through unis swap or you want to do some other complex things um this is what composibility allows for you um so you might think well composibility is well kind of easy right you just essentially chain up a bunch function calls inside another function. So for example, we have this function called LZ receive on the destination chain uh which delivers the actual message to the app on the destination chain. Um and uh what you can essentially do to be honest right is just call contract A function A on there and then contract B and contract C.
Uh but the problem with this is since blockchains are atomic and all transactions on blockchains are atomic. Um if even one call fails or reverts the whole contract will the whole contract call will revert. Um so obviously that is not ideal. Um we solve this by introducing something called horizontal composability. So remember I told you about this executor that essentially is the one calling the contract um and making the transaction on the destination chain.
So this same executor can be used the for the purposes of calling that sequence of transactions and sequence of custom logic that you have on the destination chain for example supply it to a or swap on unis swap. Um so again you could essentially think of these are like checkpoints that the executor would do on the destination chain. First, it would receive the tokens and send it to whoever needs to get it. And then secondly, it would just um call another contract, for example, um unis swap ra. Um one really cool example of composers is something called an omni chain vault.
So, we built this standard which essentially is a ERC 4626. If you guys don't know what that is, essentially it's a standard on Ethereum that would allow um you to build a wault that can uh accept deposits and minced a share token kind of um saying that okay you as the user or your user have um deposited to this vault and and received this amount of ratio of the vault uh back to the user. So um when doing it on a single chain obviously things make sense but what if you want to accept deposits from multiple chains and also receive those tokens the the shared tokens on multiple chains. So that's when omni chain vaults come in right. So the standard flow for any omni chain wault is basically the user on for example arbitum um sends a call to send for example USDC from arbitum to any hub chain like base right under the hood there's obviously the layer zero message um the tokens will be uh you'll receive the tokens on the destination chain and then the composer would actually call uh with those USDC tokens that you sent would call the um ERC 4626 uh vault and deposit those tokens in there and then also since those shares that are minted are ERC20 tokens, they can be wrapped as an OFT adapter and so those instantly become omni chain as well and you can transfer it to any other spoke chain or what we call yeah spoke chains that you um can define and configure yourself.
Uh you could essentially sh send those share tokens to any other spoke chain. Um some things to note about just composing in general is uh um the fact that again the executor is the one actually calling the functions. So it is really important to set enough gas because again from a user standpoint all they did was sign one transaction and send on the source chain. Everything else is working under the hood. Um so the important thing that you need to note right is to quote um the fees from these workers and the executor um beforehand so that you can essentially uh be sure that the transaction won't revert because of lack of gas.
So with the options builder or we call what we call like basically how to set gas right um you can essentially just call LZ receive option and set the gas limit for um the executor calling LZ receive. The same thing goes for LZ compose options which essentially sets the gas limit for when the executor calls LZ compose. Um and yeah I wanted to show you a quick demo of um the AVA composer. So essentially what this demo is going to show you is a user calling send on any arbitrary OFT contract and uh sending a message to chain B in this case will be base mainet um receiving the tokens and queuing up a composed message essentially saying that I want to um deposit something into a lending protocol. In this case, we're going to use a v3 and the user on the destination chain will receive um the receipt token saying yeah uh we have essentially deposited into a successfully.
So um let's go to the repo. So if you're again um if you're in E global discord, you can just go to partner layer zero um channel and uh yeah, you can see the link to this repo over there. Um so let's go through the readme I guess real quick. Yeah you can just clone the repo um CD into it and important thing you need is the private key. So uh in this env.
ample we have the private key of the deployer who's actually going to be deploying the um token standards. Um after that you have to set your chains right so there's a hardhead config.ts file where you set the chains that you're going to be working with. So in this case it's going to be the arbitum mainet where the user is going to be sending USDC and uh base mainet where the user is going to receive USDC and instantly deposit into an a um contract on base. Um after we've done that and yes I went ahead and already configured both arbitro mainet and base mainet um yeah you can install and compile.
So the first thing you need to do is deploy the composer contract right and uh if you wonder how the composer contract looks let me just yeah so essentially we have to import a couple of interfaces like I zero composer which essentially um defines the lzcompose function that will be called by the executor um as well as the a v3 composer which essentially is just some errors and some events that I made for uh mainly for code organizing right um the main Everything in the constructor that we are doing is uh again the constructor receives the a pool contract right um this is the contract on a that receives uh deposits as well as theft contract that we are going to be using. So in this case we're going to use targetate as I said um you could either deploy uh your own custom OFTs for this or you could use Stargate because Stargate at the end of the day are also interfaced in the same way as OFTs. Um yeah so essentially in the constructor we set uh all of these variables um and also give a one-time approval for the a contract to spend tokens um on our behalf on the beha on the behalf of the composer in this case. Um and the most important uh contract call here or the function here is called LZ compose. Um so um I'm just going to skip through this but yeah the important import what's important to note is this OFT compose message codec which is essentially the standard uh that we use or the library that we use to encode data on the source chain and also consequently decode um data on the destination chain right so um we going to be passing the amount of tokens to supply and decoding that from the message itself um we're also going to be decod coding the um address to.
So essentially the a.supply function what it does is it um takes in a couple of values the amounts that how much you want to supply which token you're supplying. In our case it's USDC and this third parameter is the address of the user who wants to re receive the receipt token. Um so this is what we kind of encode into our initial send from the source chain. Obviously if anything goes wrong we call the refund function.
The refund function again sends a layer zero message back. So you can even refund back to the source chain even though the tokens are on the destination chain already. Um so this should be pretty straightforward uh wrapped in try try and catch um so that yeah we know when something goes bad but yeah the main thing here is um we need to deploy the composer contract on base mainet right. Um again as I said uh we need some values to pass into the constructor. So we need the A v3 pool address.
Uh where you can grab that is on the A docs, right? Um you can go here and grab the addresses. The target chain is BV3 mainet. So let's just grab this contract address, right? And the second thing is target pool address.
This target pool address you can also find under I left this in discord also under links but um there's this page on our docs called OFT ecosystem and target Stargate assets. You can essentially just uh filter for all the tokens theft tokens that are issued by Stargate if the Wi-Fi allows me. Yes, thank you. Um give it a minute. Yes.
And then look for USDC or I guess look for um base That is so cool. All right. Um, so you can see the contract here. So we see the issuer is Stargate. The type is Stargate pool and the contract address is this OFT field right here.
Right. Uh, and then you just attach it here, right? Um, yeah. So the call the the task itself is PNPM hard hat LZ deploy. um with the tags as the name of the contract.
So what this would allow you is give you a CLI to deploy to your defined hardhead uh chains. So in this case we'll deploy the deploy the composer to base mainet um skip 3Ds and yeah you will see that our contract has been deployed to this address. You could also find the contract address under deployments uh and a v3 composer json. So here's the address. So let's also test the send functionality.
So again what we're going to be doing is sending USDC from arbitum to base and then immediately supplying it into a right. So in the readme that I provided um there are essentially a couple of things that we need to pass into here but it's fine right so first of all is the network uh from which we are calling. So essentially arbitr um the amount in local decimals. Yeah importantly it's in local decimals. So the last time I checked, USDC has six decimals on base and on arbitum.
So we're just going to be sending one USDC in this case. So uh one with six zeros, you want to attach your composer address as well. Again, you can find it over here um under deployments, right? Um you also want the destination endpoint ID. So where where do you find that?
Um, essentially on that same page where I showed you where you can find the Stargate contracts, um, you can also see the endpoint ID. So the endpoint ID is essentially the ID of the contract um, that we as layer zero deployed on the destination chain. So I'll yeah, so it's right here, endpoint ID. Um, and importantly, we need the contract for the Stargate pool or any OFT that we are quoting from on the source chain. So in this case it's not base, it's arbitum.
Obviously you can automate this process. Um but yeah I figured I would want to show it to you guys since um we're doing this from scratch. Um so this should be enough right? So the task name is a supply and uh it's just PNPM hardp a supply. So first thing it's going to do is going to prepare the stargate supply compose right.
Um it's going to check for any current allowances and then it's going to submit a transaction. Okay. Um so we get this transaction hash where you can go to LZ scan and uh check the status of this transaction again. Hopefully the network will allow us to view this. Okay.
So what are we waiting for? We are waiting for the required DVNs or verifiers to verify that this message has uh not been tampered with. Right? So in this case the verifier the verifiers are Nethermind and the Stargate DVN itself. we commit the message um and the executor is going to call LZ receive first and we see that succeeded and it's going to call the LZ compose next.
So again we see that this is succeeded as well. Um the token transferred uh you can see that it's was 1 USDC and without even going to a we should see 1 a USDC which is essentially the receipt token uh that a sends back to the user when the supply was successful. Um let's also double check whether this has worked or not. Um this is yeah the a interface and as you can see one like close to one USDC obviously um but yeah $1 worth of USDC has been supplied uh into a should be it for the workshop. If you have any questions, let me know.
In this example, for example,
sorry. Uh, so in this in this repo you have for the example, if we want to withdraw the fonts, it's going to be um crosschain too or it's going to be on base even though I sent it from an arbitrum. Is that logic handled?
Yeah. Yeah. Yeah, you can definitely um it's not defined in the repo that I provided, but again um yeah, all Lzio is is sending crosschain messages. So you can uh essentially just um use that same logic to withdraw the funds or even call like other functions on other contracts. For example, um the swap call the swap router for unis swap and swap the tokens immediately or obviously like do whatever custom logic you guys as hackers that like you guys are building um more exciting things obviously than just swapping and supplying but uh yeah uh whatever you feel like uh is needed um I think you can definitely come by our booth or ask the question on discord uh we can help you out here uh but generally yeah this should be possible
perfect thank you Uh do you repeat uh how I get uh the composer uh hash?
Oh, the contract address.
Yeah.
Yeah. Yeah. Um yeah. So the way we have the repo structured is um there is this deployments directory, right? After calling uh sorry uh after calling pnpm hard hat um yeah after calling this command pnpm hard hat lz deploy um essentially what you is going to be created is this deployments folder right it's going to have the chain u inside of it there's going to be a directory for the chain where you deployed the contract and you're going to have the name of the contractjson uh which will have the contract address defined in All right, I think that is it.
Thank you so much. [Music]
Automatic transcript — names and jargon may be misspelled.