Under Construction
What's an Argobytes? It's a non-sense word that makes searching easy. I'll probably rename it.
The initial use of these contracts was atomic arbitrage, but they can be used for combining all sorts of ethereum smart contract functions.
There are many components: ArgobytesProxy, ArgobytesMulticall, ArgobytesTrader, ArgobytesAuthority, ArgobytesFactory19, and a bunch Actions.
The proxy is a lightweight contract that uses "delegatecall" to use another contract's logic but with its own state and balances. Anyone can deploy an "action" contract with new logic and then anyone else can use it through their proxy.
The other contract will have complete control of the proxy's state and balances, so the proxy must only ever call trusted contracts!
The proxy has an immutable owner. By default, only the owner can use the proxy.
Owners can opt into more advanced authentication that lets them approve other addresses to call specific functions on specific contracts. Done properly, this allows for some very powerful features.
A common pattern will be combining a trade and a deposit into a DeFi protocol.
If the owner of the proxy is a smart contract like Compound's Timelock, then very powerful security should be possible.
An extension to ArgobytesProxy that can also manage flash loans from Aave or your own funds. With this contract you (or someone you authorize) can perform actions with borrowed capital.
Aave currently charges a 0.09% fee for flash loans.
A common pattern will be sending one setup transaction that calls approve
on an ERC-20 token for the ArgobytesFlashBorrower. Then send a second transaction that calls ArgobytesFlashBorrower's flashloanToOwner
to do an arbitrage trade.
A surprisingly simple, but hopefully powerful way to authorize other addresses to use your proxy.
For each authorization, you specify an addresses to call a specific function on a specific contract. Approval can be revoked at any time. Given a properly designed contract this should allow you to safely delegate permissions to others without them having custody of your funds.
The Factory contract can be used to deploy any other contract as well as clones of the Proxy contract.
For a gas optimization, the address of the target contract must begin with at least one zero byte (0x00...)
Every user needs their own proxy contract, but deploying it requires 672k gas. So instead of every user spending that gas, the proxy contract is deployed once. Then, the Factory's cloneProxy
function is called to deploy a modified EIP-1167 proxy for <70k gas. This proxy is hard coded to use the ArgobytesProxy
contract for all its logic.
The clones and their owner cannot be changed. If a new ArgobytesProxy is released, a new clone will need to be created. Because this is cheap, I think it is far preferable to the complexity of upgradable contracts.
When creating new contracts, the Factory can use salts generated by ERADICATE2 to create customized addresses that require less gas to use.
The various "Action" contracts are for taking some sort of action on one or more of the many different projects available on Ethereum. The most common action is to trade one token for another.
- Argobytes Trader: See below
- leverageCYY3CRV: See below
- Exchanges
- AbstractERC20Exchange: The common bits used by most any exchange that trades ERC20 tokens. It isn't necessary to use this, but it is helpful.
- ExampleAction: This action is just used for tests and isn't for mainnet. It can be a useful starting point when writing a new action.
- CurveFiAction: Trade tokens on https://curve.fi
- KyberAction: Trade tokens on https://kyberswap.com
- UniswapV1Action, UniswapV2Action: Trade tokens on https://app.uniswap.org/
- Weth9Action: Wrap and unwrap ETH
Lots more actions are in development. Anyone can write an action.
Actions must be very carefully designed if they use state (most should probably use immutables instead). If the action does not use state, it can be delegate called; this saves gas.
Under construction.
Most sets of actions will probably involve trading tokens. The Trader's atomicTrade
function uses ERC-20 approvals and ArgobytesMulticall to transfer and trade tokens. This can be helpful for aggregating trades across multiple exchanges.
The Trader's *Arbitrage
functions are designed so that unless the trade completes with a positive arbitrage, the entire transaction reverts. This means that you can approve other people or contracts to trade with your balances. atomicArbitrage
uses your own funds to do the arbitrage.
When combined with the ArgobytesFlashBorrower, this will allow atomic arbitrage without any needing any capital.
Under construction.
- Start with some DAI/USDC/USDT/3CRV/y3CRV
- Flash loan more DAI (7.4x more)
- Deposit DAI/USDC/USDT into Curve's 3CRV
- Deposit 3CRV into Yearn's y3CRV
- Deposit Yearn's y3CRV into Cream+Yearn's cyy3CRV
- Borrow DAI from Cream+Yearn
- Pay back flashloan
Reverse of EnterCYY3CRVAction.
- Get an account with https://rivet.cloud or https://infura.io or install
geth
(or another node that is compatible withganache-cli --fork
). For geth, read this. - Install
python3-dev
andpython3-venv
- Install
node
v14 (andnpm
v6) (I like to usenvm install 14
) - Install
yarn
(npm install -g yarn
) - Make a
.env
file:# We use etherscan for fetching mainnet contract data (https://etherscan.io/myapikey) export ETHERSCAN_TOKEN="XXX" # URL for a mainnet Ethereum node (to fork at a specific block, append "@BLOCKNUM") export FORK_RPC="ws://localhost:8546" # Tracing transactions in ganache can use a lot more than the default 1.7GB export NODE_OPTIONS="--max-old-space-size=8096" # Infura key (only if you don't run your own node) export WEB3_INFURA_PROJECT_ID="YYY"
- Run
./scripts/setup.sh
- Run
./venv/bin/brownie networks import brownie-network-config.yaml True
- If you run your own Ethereum node, edit the
mainnet
section of~/.brownie/network-config.yaml
Run:
. ./scripts/activate
brownie compile
# test development deploy scripts
# make sure nothing is using localhost:8575 before running this command!
./scripts/test-deploy.sh
# have brownie setup a ganache and run unit tests
# make sure nothing is using localhost:8565 before running this command!
./scripts/test.sh
# run ganache forking mainnet at localhost:8555 (http or websocket)
# i point my arbitrage finding code (in a seperate repo) at this node
./scripts/staging-ganache.sh
# deploy this project's contracts to staging-ganache
EXPORT_ARTIFACTS=0 ./scripts/staging-deploy.sh
# export contract abi .jsons and deployed addresses to ../argobytes-backend/contracts/
# This is called automatically by `EXPORT_ARTIFACTS=1 staging-deploy.sh`
./scripts/export.sh
# interact with the contracts from a fun interface
./scripts/eth95.sh
Run:
pipx install pip-tools
pip-compile --upgrade requirements.in
pip install -U -r requirements.txt
yarn upgrade
Run:
isort .
autoflake -r --in-place --remove-all-unused-imports argobytes setup.py tests
black --line-length 120 argobytes setup.py tests
yarn run prettier
TODO: automate this
This project wouldn't be possible without so many other projects.
- Brownie
- Solidity
- Geth
- Kollateral
- OpenZeppelin
- Ganache-cli
- Etherscan
- and many others