Tutorial: Executing swap with Shell Protocol
Last updated
Last updated
This tutorial will walk you through the example of executing a swap (DAI <> USDC) on Arbitrum Goerli testnet using the two most important Shell Protocol components: the , a unified accounting system, and , Shell's novel AMM primitive.
Clone the Shell Protocol public repo, cd
into it and run npm install
In the root folder, go to hardhat.config.js
and add your private key on line 27.
WARNING: Do not just simply paste the private key. Use something like dot-env
and environment variables instead. Be sure that you ad the file containing secrets to the .gitignore
Be sure that your account has enough test tokens on Arbitrum Goerli network. You can use this faucet to fund your account . You can also obtain up to 1000 testnet ERC-20 tokens by calling the claimTokens
function on the following contract:
Now go to scripts
folder and create new file swap.js
. We will write the whole swap logic inside this file and let the hardhat execute the script.
The first thing we will do is to import hardhat and create an empty main()
function which will be called upon running swap.js
by the Hardhat. It's a standard way of writing .
Wrap 100 DAI to the Ocean
Ask Proteus AMM Engine to calculate how many USDC should we get for 100 DAIs
Ask The Ocean to transfer computed amount of USDC to our wallet
Now that we know what to do, we need to determine how to do it. As we already mentioned, The Ocean executes instructions by passing Ocean Interactions to it in order we want them to be executed. So, in this case we need to pass the following interactions:
WrapErc20
with the DAI token address as an input token and amount set to the 100
ComputeOutputAmount
passing DAI as an input token, 100 as amount and USDC as an output token
UnwrapErc20
to transfer USDC from the Ocean to the specified address
So, the next step is to encode this three interactions and prepare them for execution.
Interactions within the Ocean are uniformly encoded via the Interaction
struct.
That means that we have to create and array of three interaction objects and we will use helper methods for that. Helper methods for creating correct format interaction objects can be found inside interactions.js
file in the utils-js
folder. We will need wrapERC20
, computeInputAmount
and unwrapERC20
helper method specifically so let's import them and see how to use them.
Ok, but what are these "WRAPPED_DAI_OCEAN_ID"
and "WRAPPED_USDC_OCEAN_ID"
that we are passing as input and output tokens to the computeInputAmount
helper function?
Let's see what we have so far. We have created an instance of the Ocean contract and we have encrypted three interactions we want to execute. All we have to do now is to tell the Ocean to execute them.
We will use another helper function executeInteractions
defined in index.js
under the utils-js
folder. This helper method receives three params: an instance of the Ocean contract, signer and an array of interactons.
All this helper method does is it calculates interaction IDs and calls an Ocean contract method doMultipleInteractions
on the behalf of signer.
We already have an instance of the Ocean created at line 7 and an array of interactions prepared. We just need a signer. Let's fetch it with the etherjs
library and place it above the Ocean instance creation on line 7.
Only thing we have to do now in order to complete the swap and this tutorial is to call the executeInteractions
First thing we will need is an instance of the Ocean smart contract. As Shell Protocol's accounting system, the Ocean is responsible for updating balances and "moving" tokens between the user and the AMM. It's not necessary that you understand how Ocean works for the sake of this tutorial, but if you want to learn more you can start read the in the deep dive section. Note that reading section before that is highly recommended. So let's create and instance of The Ocean in line 4:
You should pass the correct Ocean contract address that can be found .
Congratulations! We just created and instance of the Ocean smart contract. Now we have to pass to that instance a set of instructions (as ) we want it to execute. In order to swap 100 DAI for USDC we will need to do the following:
Now we just have to pass the right values instead of the template strings. DAI contract address on Arbitrum Goerli is while USDC is at the following address .
Finally, DAI USDC Pool address we need is . All Proteus pool address can be found in .
Well, as an accounting system Ocean is responsible for handling both tokens from the external ledgers (ERC20, ERC721, ERC1155), i.e. wrapped tokens, and Ocean native tokens. In order to keep the track of everything, every token inside the Ocean has its own ID which we call Ocean ID.
We won't be going into explaining this concept here as it's not necessary to understand how it works to complete this tutorial, it's throughly explained in the Ocean page under the section.
All we need to know right now is that we have another helper function which we can use to get the correct token id. The helper method name is calculateWrappedTokenId and it's located inside utils.js
file in the utils-js
folder.
Let's swap the template strings with the real values:
Congratulations! You have successfully completed a swap using Shell Protocol's accounting contract, The Ocean and native AMM engine Proteus. In this tutorial we tried to explain the complete system form a higher level, using as much abstractions as possible without loosing clarity, while also not going deeper than we need into specifics. In the section you'll be able to go behind those abstractions and learn the inner workings of every component used in this example.
Since you have successfully completed this tutorial you deserve appreciation.Don't forget to !