Skip to content

Commit

Permalink
Uniswap v3 valuation and swaps on Base (#255)
Browse files Browse the repository at this point in the history
- Add Multicall3 support in `multicall_batcher` module
- Add `SwapRouter02` support on Base for doing Uniswap v3 swaps
- Add Uniswap V3 quoter for the valuation
- Add `buy_tokens()` helper to buy multiple tokens once, automatically look up best routes
- Refactor things around
  • Loading branch information
miohtama authored Dec 24, 2024
1 parent 434d7d3 commit 516f88f
Show file tree
Hide file tree
Showing 38 changed files with 3,177 additions and 275 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ docs/source/tutorials/aave.json
contracts/aave-v3-deploy/hardhat-deployment-export.json

# pyenv local
.python-version
.python-version

contracts/lagoon-v0
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Current

- Add Multicall3 support in `multicall_batcher` module
- Add `SwapRouter02` support on Base for doing Uniswap v3 swaps
- Add Uniswap V3 quoter for the valuation
- Add `buy_tokens()` helper to buy multiple tokens once, automatically look up best routes

# 0.27

- Add: Support for [Velvet Capital vaults](https://www.velvet.capital/)
Expand Down
48 changes: 44 additions & 4 deletions eth_defi/abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import re
from functools import lru_cache
from pathlib import Path
from typing import Optional, Sequence, Type, Union
from typing import Optional, Sequence, Type, Union, Any

import eth_abi
from eth_abi import decode
Expand All @@ -27,12 +27,20 @@
# Cache loaded ABI files in-process memory for speedup
from web3.datastructures import AttributeDict

from eth_defi.utils import ZERO_ADDRESS_STR

# How big are our ABI and contract caches
_CACHE_SIZE = 512


#: Ethereum 0x0000000000000000000000000000000000000000 address as a string.
#:
#: Legacy. Use one below.
#:
ZERO_ADDRESS_STR = "0x0000000000000000000000000000000000000000"

#: Ethereum 0x0000000000000000000000000000000000000000 address
ZERO_ADDRESS = ZERO_ADDRESS_STR


@lru_cache(maxsize=_CACHE_SIZE)
def get_abi_by_filename(fname: str) -> dict:
"""Reads a embedded ABI file and returns it.
Expand Down Expand Up @@ -288,6 +296,34 @@ def encode_function_args(func: ContractFunction, args: Sequence) -> bytes:
return encoded_args


def decode_function_output(func: ContractFunction, data: bytes) -> Any:
"""Decode raw return value of Solidity function using Contract proxy object.
Uses `web3.Contract.functions` prepared function as the ABI source.
:param func:
Function which arguments we are going to encode.
Must be bound.
:param result:
Raw encoded Solidity bytes.
"""
assert isinstance(func, ContractFunction)

web3 = func.w3

fn_abi, fn_selector, aligned_fn_arguments = get_function_info(
func.fn_name,
web3.codec,
func.contract_abi,
args=func.args,
)
arg_types = [t["type"] for t in fn_abi["outputs"]]
decoded_out = eth_abi.decode(arg_types, data)
return decoded_out


def encode_function_call(
func: ContractFunction,
args: Sequence,
Expand Down Expand Up @@ -320,7 +356,10 @@ def encode_function_call(
fn_abi,
args,
)
encoded = encode_abi(w3, fn_abi, fn_arguments, fn_selector)
try:
encoded = encode_abi(w3, fn_abi, fn_arguments, fn_selector)
except Exception as e:
raise RuntimeError(f"Could not encode ABI: {fn_abi}, args: {fn_arguments}") from e
return HexBytes(encoded)


Expand Down Expand Up @@ -464,3 +503,4 @@ def get_function_selector(func: ContractFunction) -> bytes:
function_signature = _abi_to_signature(fn_abi)
fn_selector = function_signature_to_4byte_selector(function_signature) # type: ignore
return fn_selector

1 change: 1 addition & 0 deletions eth_defi/abi/multicall/IMulticall3.json

Large diffs are not rendered by default.

Loading

0 comments on commit 516f88f

Please sign in to comment.