Skip to content

Commit

Permalink
Uniswap v3 swap on Arbitrum works
Browse files Browse the repository at this point in the history
  • Loading branch information
miohtama committed Sep 26, 2024
1 parent 01e7892 commit 2c43925
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 29 deletions.
7 changes: 7 additions & 0 deletions eth_defi/aave_v3/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,22 @@ class AaveToken(NamedTuple):
},
),
# Arbitrum Mainnet (XXX TODO - add more tokens)
# https://docs.aave.com/developers/deployed-contracts/v3-mainnet/arbitrum
"arbitrum": AaveNetwork(
name="Arbitrum",
pool_address="0x794a61358D6845594F94dc1DB02A252b5b4814aD",
pool_configurator_address="0x8145eddDf43f50276641b55bd3AD95944510021E",
pool_created_at_block=7742429, # https://arbiscan.io/tx/0xf73ad5eb856faaf2eaf6e8a0823d2964e80ca4ad7cc2031f0606b158d236b5a9
# https://github.com/bgd-labs/aave-address-book/blob/main/src/AaveV3Arbitrum.sol
token_contracts={
# Aave token contracts defined in the Arbitrum network
"AAVE": AaveToken(token_address="0xba5DdD1f9d7F570dc94a51479a000E3BCE967196", deposit_address="0xf329e36C7bF6E5E86ce2150875a84Ce77f477375", variable_borrow_address="0xE80761Ea617F66F96274eA5e8c37f03960ecC679", stable_borrow_address="0xfAeF6A702D15428E588d4C0614AEFb4348D83D48", token_created_at_block=7410775), # https://arbiscan.io/address/0xba5ddd1f9d7f570dc94a51479a000e3bce967196
"WETH": AaveToken(token_address="0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", deposit_address="0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8", variable_borrow_address="0x0c84331e39d6658Cd6e6b9ba04736cC4c4734351", stable_borrow_address="0xD8Ad37849950903571df17049516a5CD4cbE55F6", token_created_at_block=55), # https://arbiscan.io/address/0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
"USDT": AaveToken(token_address="0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", deposit_address="0x6ab707Aca953eDAeFBc4fD23bA73294241490620", variable_borrow_address="0xfb00AC187a8Eb5AFAE4eACE434F493Eb62672df7", stable_borrow_address="0x70eFfc565DB6EEf7B927610155602d31b670e802", token_created_at_block=1),
# USDC native (not bridged)
"USDC": AaveToken(token_address="0xaf88d065e77c8cC2239327C5EDb3A432268e5831", deposit_address="0x724dc807b04555b71ed48a6896b6F41593b8C637", variable_borrow_address="0xf611aEb5013fD2c0511c9CD55c7dc5C1140741A6", stable_borrow_address="0xDC1fad70953Bb3918592b6fCc374fe05F5811B6a", token_created_at_block=1),
# USDC bridged
"USDC.e": AaveToken(token_address="0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", deposit_address="0x625E7708f30cA75bfd92586e17077590C60eb4cD", variable_borrow_address="0xFCCf3cAbbe80101232d343252614b6A3eE81C989", stable_borrow_address="0x307ffe186F84a3bc2613D1eA417A5737D69A7007", token_created_at_block=1),
},
),
# Fantom Mainnet (XXX TODO - add more tokens)
Expand Down
15 changes: 14 additions & 1 deletion eth_defi/enzyme/generic_adapter_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ def deploy_vault_with_generic_adapter(
deployer.sync_nonce(web3)

if terms_of_service is not None:
assert denomination_asset.address
assert comptroller.address
assert terms_of_service.address
payment_forwarder, tx_hash = deploy_contract_with_forge(
web3,
CONTRACTS_ROOT / "in-house",
Expand Down Expand Up @@ -411,8 +414,13 @@ def deploy_guard(
case 1:
uniswap_v2_router = UNISWAP_V2_DEPLOYMENTS["ethereum"]["router"]
uniswap_v3_router = UNISWAP_V3_DEPLOYMENTS["ethereum"]["router"]
case 42161:
if uniswap_v2:
raise NotImplementedError(f"Uniswap v2 not configured for Arbitrum yet")
uniswap_v2_router = None
uniswap_v3_router = UNISWAP_V3_DEPLOYMENTS["arbitrum"]["router"]
case _:
logger.info("Uniswap not supported for chain %d", web3.eth.chain_id)
logger.error("Uniswap not supported for chain %d", web3.eth.chain_id)
uniswap_v2_router = None
uniswap_v3_router = None

Expand Down Expand Up @@ -475,9 +483,14 @@ def deploy_guard(
case 42161:
# Arbitrum
aave_tokens = AAVE_V3_NETWORKS["arbitrum"].token_contracts

# TODO: We automatically list all main a tokens as allowed assets
# we should limit here only to what the strategy needs,
# as these tokens may have their liquidity to dry up in the future
for symbol, token in aave_tokens.items():
logger.info(
"Aave whitelisting for pool %s, atoken:%s address: %s",
symbol,
aave_pool_address,
token.token_address,
)
Expand Down
46 changes: 18 additions & 28 deletions tests/enzyme/test_arbitrum_trade.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
"""
import os
import datetime
import random

import pytest

Expand All @@ -17,18 +15,11 @@

from web3 import Web3
from web3.contract import Contract
from web3.middleware import construct_sign_and_send_raw_middleware

from eth_defi.abi import get_contract
from eth_defi.abi import get_deployed_contract
from eth_defi.enzyme.deployment import ARBITRUM_DEPLOYMENT
from eth_defi.provider.anvil import AnvilLaunch, launch_anvil
from eth_defi.terms_of_service.acceptance_message import (
generate_acceptance_message,
get_signing_hash,
sign_terms_of_service,
)
from eth_defi.deploy import deploy_contract
from eth_defi.enzyme.deployment import EnzymeDeployment, RateAsset
from eth_defi.enzyme.deployment import EnzymeDeployment
from eth_defi.enzyme.generic_adapter_vault import deploy_vault_with_generic_adapter
from eth_defi.enzyme.uniswap_v3 import prepare_swap
from eth_defi.enzyme.vault import Vault
Expand All @@ -44,6 +35,7 @@
)
from eth_defi.uniswap_v3.pool import PoolDetails, fetch_pool_details


JSON_RPC_ARBITRUM = os.environ.get("JSON_RPC_ARBITRUM")
pytestmark = pytest.mark.skipif(not JSON_RPC_ARBITRUM, reason="Set JSON_RPC_ARBITRUM to run this test")

Expand Down Expand Up @@ -97,7 +89,8 @@ def usdt(web3) -> TokenDetails:

@pytest.fixture
def weth(web3) -> TokenDetails:
details = fetch_erc20_details(web3, "0xec32aad0e8fc6851f4ba024b33de09607190ce9b")
# https://arbiscan.io/token/0x82af49447d8a07e3bd95bd0d56f35241523fbab1
details = fetch_erc20_details(web3, "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
return details


Expand All @@ -118,9 +111,10 @@ def enzyme(

@pytest.fixture()
def terms_of_service(web3) -> Contract:
tos = get_contract(
tos = get_deployed_contract(
web3,
"terms-of-service/TermsOfService.json",
"0xDCD7C644a6AA72eb2f86781175b18ADc30Aa4f4d", # https://github.com/tradingstrategy-ai/terms-of-service
)
return tos

Expand Down Expand Up @@ -170,26 +164,23 @@ def vault(
terms_of_service=terms_of_service,
whitelisted_assets=[weth, wbtc, usdt],
uniswap_v3=True,
uniswap_v2=False,
one_delta=False,
aave=True,
)


@pytest.fixture()
def uniswap(
def uniswap_v3(
web3: Web3,
weth: Contract,
usdc: Contract,
mln: Contract,
deployer: str,
) -> UniswapV3Deployment:
addresses = UNISWAP_V3_DEPLOYMENTS["arbitrum"]
uniswap = fetch_deployment(
web3,
addresses["factory"],
addresses["router"],
addresses["position_manager"],
addresses["quoter_address"],
addresses["quoter"],
)
return uniswap

Expand All @@ -208,7 +199,6 @@ def test_enzyme_uniswap_v3_arbitrum(
usdt_whale,
enzyme: EnzymeDeployment,
vault: Vault,
vault_investor: LocalAccount,
weth: TokenDetails,
usdt: TokenDetails,
wbtc: TokenDetails,
Expand All @@ -217,19 +207,19 @@ def test_enzyme_uniswap_v3_arbitrum(
):
"""Make a swap that goes through the call guard."""

# Check that all the assets are supported on the Enzyme protocol level
# (Separate from our guard whitelist)
assert vault.is_supported_asset(usdt.address)
assert vault.is_supported_asset(weth.address)
assert vault.is_supported_asset(wbtc.address)

tx_hash = usdt.contract.functions.transfer(
user_1,
500 * 10 ** 6,
).transact({"from": usdt_whale})
assert_transaction_success_with_explanation(web3, tx_hash)
assert usdt.fetch_balance_of(usdt_whale) > 500, f"Whale balance is {usdt.fetch_balance_of(usdt_whale)}"

tx_hash = usdt.contract.functions.transfer(user_1, 500 * 10 ** 6).transact({"from": deployer})
# Get USDT, to the initial shares buy
tx_hash = usdt.contract.functions.transfer(user_1, 500 * 10 ** 6,).transact({"from": usdt_whale})
assert_transaction_success_with_explanation(web3, tx_hash)
tx_hash = usdt.contract.functions.approve(vault.comptroller.address, 500 * 10 ** 6).transact({"from": user_1})
assert_transaction_success_with_explanation(web3, tx_hash)

tx_hash = vault.comptroller.functions.buyShares(500 * 10 ** 6, 1).transact({"from": user_1})
assert_transaction_success_with_explanation(web3, tx_hash)

Expand All @@ -254,4 +244,4 @@ def test_enzyme_uniswap_v3_arbitrum(
assert_transaction_success_with_explanation(web3, tx_hash)

# Bought ETH landed in the vault
assert weth.contract.functions.balanceOf(vault.address).call() == pytest.approx(0.123090978678222650 * 10**18)
assert 0.01 < weth.fetch_balance_of(vault.address) < 1

0 comments on commit 2c43925

Please sign in to comment.