Beyond the EVM: Triggering External Logic with Solidity Contracts
EthCC[8] · 2 Jul 2025 · 23:27
Julia Gallen and Miroslav Nedelchev demonstrate Solidity contracts triggering external logic on Solana. The workshop uses Neon EVM precompiles and libraries to extend application composability with EVM tools.
Speakers
Topics
From EthCC[8], hosted by Ethereum France.
Transcript
U hi everyone. Uh thank you so much for sticking around for this presentation. Um uh my name is Julia. I work at Neonvm as a developer relations manager and uh today I want to talk about going beyond the EVM and triggering external logic from your solidity contracts. And in particular, we are going to be talking about how to trigger Salana programs from EVM uh projects. Um my name is Julia Galin again. Um I entered the industry in uh 2018 and I work in various EVM projects from wallets to infra uh to even prediction markets. Uh but I do have a very different
background. I come from computational linguistics originally and uh at the moment I work at UNVM to help EVM developers bridge this gap between EVM and Salana and expand their user base to Salana uh users and also to Salana liquidity. So um usually expanding to Salana from EVM is a very painful project because obviously you will need to maintain two code bases. you will need to learn Rust and create your um project in Rust to interact with Salena programs or uh another way would be to use a bridge but this will add an overhead and neonvm uh brings the two worlds together in the
best way possible because uh for EVM developers it means that uh there is uh no painful learning of Salana architecture or um no need to learn Rust. Uh they can stay within their comfort zones of Solidity and EVM infrastructure, all the uh familiar tooling. They can use hard head foundry uh they can use remix uh uh and they can connect to ethereum RPCs as they usually do and at the same time they can add the good things that Salana has uh which is the parallel execution which is lower gas fees and obviously a new uh user base and um new liquidity pools. Um how
does newbian do that? Well, it has two main components which allow for this uh function to happen. And these components are the neon proxy uh over there and the new NEVM program. And uh the end a goal for a for an app here is to be able to connect uh the users with both EVM and Salana wallets and interact with Salana programs and SPL tokens. So tokens on Salana and for both neon makes a native experience which means they which means that they don't have to use a bridge or
anything like that. And EVM wallets are just connected to a DEP front end. They send a typical EVM transaction which is picked up by Neonroxy which is just a typical Ethereum RPC and Neonroxy translates this EVM bite code EVM transaction into a Salana style transaction. uh we are going to see later how exactly this wrapping happens and it sends it to the neonvm program which is deployed on Salana and contains pre-ompiled contracts that execute the this um double hybrid transaction natively directly on Salana and uh thus
the EVM wallet can connect to SPL tokens and to Salana programs such as all kinds of Salana dexes is Jupiter, Radium, Orca, etc. And at the same time, Neonvm allows to use Salana wallets to connect to all these uh kinds of Salana programs. But you would say, why would you need an NEOVM for that? Because you allow your EVM DAB to give Salana native experience to uh people who have Salana wallets. So basically they connect to your EVM DEP with a Salana wallet and send Salana transaction which contains the EVM bite code to newvm program that also executes this directly and natively
on Salana. So um before I show you how new NVM wraps an Ethereum transaction into a Salana transaction, let's briefly compare what EVM and Salana transaction objects and well as you all know as this is an EVM transaction object which is very simple, very straightforward. Uh but this is a Salana transaction object and it is complicated. Uh first of all it is instruction based. So you can see that all these um operations are packed into instructions and for each instruction you have to generate a very particular list of
accounts. Um well like everything is an account on Salana. I'm not sure how uh well you're familiar with Salana but basically Salana treats uh like tokens as accounts uh like everything basically is an account on Salana and you need to generate very explicitly all these accounts in a very particular order here. So to be able to do that uh neonvm uh sorry I'm not moving the right direction. So uh new VM basically wraps this Ethereum like transaction into the data field of a Salana transaction and it adds an um EVM program address uh in accounts list into the program index
field and it also generates all the required accounts uh in the libraries and puts them into the accounts list on Salana. So it kind of um both splits the Ethereum transaction and puts that into Salana transaction but also it generates all the needed uh accounts and translates the instructions to be able to put them within Salana transaction um and it does it with the help of this composability feature which consists of libraries and pre-ompiled contracts. So uh at the moment um composability uh is available for uh these programs on
Salana and these are uh the native programs and a couple of custom programs on Salana. Uh so that you can connect uh your EVM project to um system program which handles account creation to SPL token program which handles everything related to tokens. uh the associated token program which handles the creation of associated token accounts which is um like an account on Solana um and radium dex and metaplex for managing metadata. Uh so this is the first part of composibility the pre-ompiled contract and uh this is the basic structure of
the pre-ompiled contract. Uh this one is called I call Salana and this one is a major pre-ompile because it handles the execution. Uh so basically it uh um handles the instruction then it uh also gives us the pair account uh with a getter and it also gives us a salana address for neon address which we need for authentication and um basically the main function here is the execution because I call Solana pre-ompile is the one you send your function calls to to be able to execute them within Salana
and these pre-ompiles including the I call Salana can access Salana state they can create accounts execute instructions on Salana and uh a very cool thing is that uh they all also can batch multiple instructions to be executed within one new NVM transactions. Uh for example, all these uh instructions like create an account, initialize the token mint, create metadata for this account and mint to an account can be all put together and sent in one transaction.
And uh the second part of composibility is uh the libraries. Uh and uh the uh composibility libraries basically uh help with um uh creating these instructions with the helper functions, getting data uh from Salana state with a getter functions, handling errors with the custom errors in one of the libraries that allows to um handle reverting the execution on Salana which is um a very painful topic. uh then um it has Salana constants and uh also handles Salana rent management and all kinds of calculations.
So uh basically you need to create a caller contract uh which is uh written in solidity and all you need to do to uh to make this composability work is that you need to import the libraries and use them in your function calls um and uh send the final call to um execute to the pre-ompiled contract. Uh so a caller contract um this one is attributed an account owned by new NVM program on Solana. Uh it requests a pair account. It owns the accounts that are created on Salana and also it implements the authentication logic by getting neon
address for Salana. And currently we have five libraries. uh the system program library that allows to create accounts, the uh SPL token program library that allows to manage tokens, the associated token program that allows to create ATA's associated token accounts, metaplex for metadata, and radium program for interacting with radium decks. Uh but you can also actually interact with Jupiter and Orca through the radium program and through other libraries as well. So the uh there is uh yeah like more to it than uh here in the slides.
So this is basically the basic structure of a caller contract. Uh here we have an example of a transfer function in a caller contract and it always starts with the authentication where we get our neon address using the I call Solana pre-ompile. uh then uh we also derive the ATA so that our tokens can exist on Salana. We uh format the instruction using the in um method from one of the libraries and we prepare the instruction again using the methods from our libraries and we
send the call to the um I call Salana pre-ompile to execute this instruction. Uh and uh today I want to have a bit of focus on the radium program library. So uh we are going to see how radium program library allows us to make a swap on radium dex from a solidity contract and radium program library as all the other libraries at neon consists of three things. So it has helper functions uh which generate the instructions. It it has um data library which provides getters so that we can fetch data from Solana state and we have the errors library which allows us to uh handle the
errors and this particular library uh well uh radium cpm program is actually a um analog of um unis swap v2. So um the instructions that we can generate are very much in line with what you can do with unis swap. So you can create a pool uh basically with this instruction create pool instruction you deploy a CPMM pool on radium for a token pair. Uh you can add liquidity withdraw liquidity lock liquidity and get an NFT position. Uh you can collect fees when there's been some traffic in the pool for example a swap. uh and you can uh use the swap input and swap output instructions to either make make an
exact swap for X amounts of token B or the other way around. And the getters are uh very much in line with the helper functions that we have. Uh you can get the data from the pool uh about the pool about the config uh the uh token in reserve the um LP amount that is accessible. Uh you can convert the uh LP amount to reserve amount and calculate the swap output based on swap input and slippage as well as uh do the other way around. uh calculate the swap input based on output and slippage and also pool pull conditions.
So uh the caller contract uh this caller contract is uh very much similar to the one we saw before but it has more handling of tokens uh which is uh of course obvious because we are dealing with um a swap and we need to swap one token for another and for this uh basically we pass very typical parameters uh pool id input token output token amount that we want to input and slipage and uh we generate the uh token mint using the ERC 24 SPL token which is a hybrid token created by neonvm to make
this sort of connection. Basically it is an ERC wrapper for SPL tokens. So uh if uh we need to get a SPL token we can just derive it from an ERC24 SPL and uh basically this is how we get the input and output token mints. Uh then we get the Solaner payer using the I call Salana pre-ompile. Uh then we get the associated token account using the input token mint and the payer account. And this is the associated token account to which we are going to transfer from our new VM address so that we can handle these tokens on Salana. And this is where the transfer happens. So before we
can handle the tokens on Salana, we need to move them from our EVM address to a Salana address. And this associated token account is going to uh handle the tokens later. So uh we transfer from the PDA. PDA is a program derived address which we derive from our message sender um and we move the tokens from uh this like intermediary account to an ATA associated token account and uh later we can work with this tok with these tokens on Salana. So uh this is an auxiliary part. it uh doesn't exist in all color contracts, but here we also use it
because we um optimize for gas fees using the pre-made accounts. Uh but later, as usual in all color contracts, we format the swap instruction using one of the methods from our libraries. In this case, it's swap input instruction. And we execute this swap on Salana calling the I call Salana pre-ompile. Uh yes, this is all and um the to look at the instruction that handles that within the library. Uh let's see how it does it behind the scenes. And basically this swap input instruction
um first looks very much like a color contract because we pass uh the same parameters but then we get the pool data. We get the accounts uh with their flags which is ser which is writable. Uh this is the thing that is uh generated within the swap method here. So basically this is a swap input instruction but uh there is another layer even beyond this which is a swap method where all this account creation happens but at this stage we are only getting the data.
Uh then we calculate the minimum swap amount output based on slippage and pull condition and um this is also uh happens in the library. This is not something that you have to do. And uh the next thing is that uh the library builds the swap input data uh and it converts uh big Indians to little Indians uh because Salana deals with little Indians and this is also um a conversion that happens within the library and the uh swap method which is like the uh bottom layer of everything that
happens in the swap. Um also well the beginning looks very similar. So uh we uh get the data, we get the accounts um check if uh uh we have pre-made accounts and then uh the swap method generates all these accounts in the correct order that Salana expects to have in this kind of instruction. And as you can see there are all kinds of accounts here for the payer for the tokens for the pool data the pool id. So basically here you can see that like everything is an account.
Uh then the method is assigning the serer flag uh and then uh it assigns the writable flags to the accounts that can be written to. uh they can be uh uh you can write state to them or writable are also executable uh accounts and basically by the end uh you get these two sides of the transaction. you get an EVM side and a Salana side transaction. And uh this is a screenshot from Blog Scout where we have the new NVM transaction and as you can see it contains two Salana transactions and if uh we open the Salana side
transaction um well there are like other instructions here but also these are the most important ones. You can see how many uh transfers happen here. The account creation. So first we transfer the tokens from PDA to ATA. Uh then um we uh generate all these accounts. We check the transfers. Then we make a swap to um another token and uh yeah basically that's it. Um yeah and this is how the swap happens with neonvm uh from solidity contract to um a radium dex and uh basically we saw that we used
the libraries and pre-ompiled contracts to generate the instructions uh from our color contract and we sent them to the pre-ompile which executed them on Salana and as a result we got the EVM side transaction and a Solana side transaction. Uh thank you very much for your attention. Um if you have any questions, I think we still have time. Yes. Okay. Uh can I do like interaction atomically between like EVM transaction with the Solana transaction? Um let's say I want to swap um USDC. Uh I want to
sell my ETH to USDC and then use that USDC to buy some token on Solana. Can I do it atomically within one transaction? Yes, that's exactly what you can do. Yes. uh you can uh batch those two transactions uh into one instruction well into one transaction that contains uh these instructions uh and uh yeah swap it on a salana but one transaction is happening on EVN and one transaction is happening on Solana so can it become atomically within like let's say one error revert on Solana can need also trigger reversion on EVN uh So um as I see it um that would
happen uh so if you do that through neonvm you will need to uh do that already within Salana because you will need to create uh um PDAs for both of those uh tokens and atas for those tokens and u basically you're going to um yeah maybe ignore the first step kind of and yeah may maybe not actually okay I see so it somehow need to the the two step it it's like two separate step it cannot atomically like been happen right no I mean if you first make a transfer from one EVM to another EVM and then yeah you
want to make a swap then only the second part will be uh done yeah because the use cases I mentioned is like maybe I want to do arbitrage between two chain then if one if the Solana transaction revert then I don't want to do this transaction anymore so then I have to revert my EV as EV transaction as well so then exactly yeah so that's a different use case right thanks thank you do you have any puzzle question thank you very