Skip to content

SatoshiAndKin/argobytes-contracts

Repository files navigation

Argobytes Smart Contracts

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.

ArgobytesProxy

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.

ArgobytesFlashBorrower

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.

ArgobytesAuthority

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.

ArgobytesFactory19

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.

Actions

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.

ArgobytesTrader

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.

leverageCYY3CRV

Under construction.

EnterCYY3CRVAction

  1. Start with some DAI/USDC/USDT/3CRV/y3CRV
  2. Flash loan more DAI (7.4x more)
  3. Deposit DAI/USDC/USDT into Curve's 3CRV
  4. Deposit 3CRV into Yearn's y3CRV
  5. Deposit Yearn's y3CRV into Cream+Yearn's cyy3CRV
  6. Borrow DAI from Cream+Yearn
  7. Pay back flashloan

ExitCYY3CRVAction

Reverse of EnterCYY3CRVAction.

Developing

Initial setup

  1. Get an account with https://rivet.cloud or https://infura.io or install geth (or another node that is compatible with ganache-cli --fork). For geth, read this.
  2. Install python3-dev and python3-venv
  3. Install node v14 (and npm v6) (I like to use nvm install 14)
  4. Install yarn (npm install -g yarn)
  5. 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"
    
  6. Run ./scripts/setup.sh
  7. Run ./venv/bin/brownie networks import brownie-network-config.yaml True
  8. If you run your own Ethereum node, edit the mainnet section of ~/.brownie/network-config.yaml

Development scripts

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

Upgrading dependencies

Run:

pipx install pip-tools

pip-compile --upgrade requirements.in
pip install -U -r requirements.txt
yarn upgrade

Linting

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

Thanks

This project wouldn't be possible without so many other projects.

Reading

About

Smart contracts for atomic trading

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published