Atomic Ninja is a transaction batcher, that will execute several actions within one atomic transaction.
Some say that flashloans democratize access to large amounts of capital, but that is not entirely true, until they are useable by the average investor. Nowadays to access the feature one needs deep technical logic, and good coding skills. Atomic will put this and other great tools in the hands of a lot more users.
We started with just one smart contract, that would send one transaction after another on behalf of the user. The atomic functionality is still contained in a single contract, that creates proxies for user using CREATE2 (addresses are unique per user). We also had to develop a proxy contract for all "sandwich" blocks, or blocks that need to handle a callback like flashloans.
We used Buidler to perform tests, also using a fork from the mainnet in Ganache.
For the UI we forked scratch-blocks, and tweaked for our needs (removing all blocks provided by the library and adding our own, plus some other small mods). We made those changes with extensibility in mind. Each block lives in a single JS file, the way we envision this in the future is that companies will pull request blocks that use their platforms.
We also of course used Ethers JS extensively for encoding a bunch of data and any interaction with Web3.
Currently there are bocks for ETH transfers, ERC20 Transfers, Uniswap swap (V1 and V2) and flashswap, Aave flashloan, Compound supplying and borrowing, Pooltogether, Defi Zaps, Balancer and an ENS resolver.
The dapp is served from IPFS (pinned on Pinata), and is available at atomicninja.eth and atomic.ninja.
On the left of the screen there is a list of sorted, disconnected blocks. This is your toolbox.
Drag the blocks to the workspace at the right, and join them to perform the actions you´d like.
Start with a hat shaped block such as , as they indicate the beginning of your transaction.
Once you are done, press to simulate your transaction, and to send it out!
Tip: Hover the blocks for details on how they work.
Block of this shape are initial blocks. Always start your atomic transaction with one of these. Transaction simulation and launching are blocked if you have more then one of these in the workspace.
These are special blocks that handle a callback. Set the parameters on the block as usual, and include the transaction you want to be performed by the callback inside it. Example: In the flashswap block pictured above, include within it all transactions you want executed during the flashswap (while you have the funds). The block will repay the loan after finishing the transactions (make sure you have funds then, or the transaction will fail). Transactions included after the block will then be executed normally.
This block is used to identify transactions that are executed in one shot. Most transactions will fall into this bucket, from transfering ETH and ERC20 tokens to Swaping, Borowing, Providing Liquidity and so on.
Press this button to simulate the call. Your call to the atomic contract will be encoded exactly as when you send it, but will be sent unsigned to a public node. This will indicate if the transaction will fail or succeed using the state of the latest mainnet block. Currently no feedback on failure is provided (the node provides no details on failures), if your transaction is failing, take a look and check if all your blocks have the funds to perform their action at the point of execution.
Lift off! Use this button to send out your atomic (mainnet only). This is currently disabled as we feel the tool is not ready to handle funds. Remember, this is hackathon code.
Will save the transaction to your local storage (no servers unfortunately :) so if you want to open the transaction in a different device you'll need to share it).
You'll be presented with a list of previously saved ninja transactions.
Sharing allows you to send a url out to friends or in social media. When you press share, your transaction will be uploaded to IPFS. The link to open it is copied to your clipboard, so you can paste it anywhere.
Remember that IPFS is efemeral by nature, if your transaction is not used for long enough the files will no longer be available. If you need your transactions to persist (if embedding in your website for example), we recommend using IPFS Pinata, they provide 1gb in their free tier, enough for millions of ninja transactions. Our front end is pinned in their free tier :)
This allows you to embed any transaction in your website. Embeded transactions are not editable by nature, but if the user clicks on the Atomic Ninja icon he will be taken to a full fledged editor. This features works particularly well on mobile.
Funcitonal example (thank you for sending this one out 😊):
When you start a ninja transaction a call is made for the atomic smart contract. It then creates a proxy for the user (using Create2, proxy addresses are unique per user) that then sequentially executes the transactions. Let's look with more detail into an actual transaction:
Hat Block (Ninja Transaction): The hat block does not contain any transactions, it is where you set the amount of ether to be sent along with the call.
Balancer swap block: Here we swap, ETH for DAI. This block actually packs two transactions, a deposit on WETH and then the swap.
ERC20 transfer: This block packs a transfer of 10 DAI to vitalik.eth.
Uniswap V2 FlashSwap: This is a sandwitch block, so it works in a particular way. It will call our flashswap proxy, that then will initiate the flashswap. The Uniswap exchange will than call back the proxy, that then sends the transactions packed inside the block back to the User's proxy contract for execution. After it executes all the transactions, it executes an additional transaction, that repays the flashloan.
Aave Flashloan: Also a sandwitch block, works exactly like the above.
Brag: This block will call our brag smart contract, and register your balance at the time of the call.
Atomic Ninja Tip: It just sends a small amount of ETH to our team.
Pool Together: It will send out a transaction to buy 10 tickets.
Now both flashloans(swaps) end, they are both repayed (with fees).
Compound Supply: Supplies .5 ETH liquidity on Compound finance, receive cETH.
Revert: This block forces a revert, in case you want to trace the transaction but do not want to spend your precious funds.
The transaction above does not make any sense economically (we would have burned almost 10ETH in fees), we made it with complexity in mind, to try to flex the tool as much as we could.
Both will pack the transactions the exact same way.
When you press simulate, atomic sends an eth_call (the one used to read from smart contracts) to a public node, the return value will tell you if it succeeds. If it fails, we made some EVM hackery to return the revert message from the original revert. This means that you will see a revert message from DAI smart contract for failed transfers. Some contracts of course will not have a message, and then you will see a generic error. Failed ETH transfers also do not give any feedback. We have already nailed how to present to the user the block in which the ninja tx failed, but have yet to implement it.
When you press launch, you will be prompted to sign the transaction. Lift off 🚀!
We sent the above example out, you can check it on Etherscan or with much more detail on Tenderly.
Below are the Etherscan verified contracts the transaction interacted with, also courtesy of Tenderly: