Skip to content
This repository was archived by the owner on May 3, 2024. It is now read-only.

Commit dcc221d

Browse files
authored
Add support for proxy contracts (#116)
1 parent f2d09ac commit dcc221d

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
name: Tests
32
env:
43
SDK_ALCHEMY_KEY: ${{ secrets.SDK_ALCHEMY_KEY }}
@@ -34,7 +33,7 @@ jobs:
3433
node-version: 16.x
3534

3635
- name: Install Poetry
37-
uses: snok/install-poetry@v1.1.1
36+
uses: snok/install-poetry@v1
3837
with:
3938
virtualenvs-create: true
4039
virtualenvs-in-project: true
@@ -44,4 +43,4 @@ jobs:
4443
if: steps.cache.outputs.cache-hit != 'true'
4544

4645
- name: Run Tests
47-
run: poetry run yarn add hardhat && make test
46+
run: poetry run yarn add hardhat && make test

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ packages = [
66
{include = "thirdweb"},
77
]
88
readme = "README.md"
9-
version = "3.0.0"
9+
version = "3.0.1"
1010

1111
[tool.poetry.dependencies]
1212
python = ">=3.7.1"

thirdweb/common/feature_detection.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,43 @@ def fetch_contract_metadata_from_address(
3131

3232
return fetch_contract_metadata(metadata_uri, storage)
3333

34+
def extract_minimal_proxy_implementation_address(bytecode: HexBytes) -> str:
35+
# EIP-1167 clone minimal proxy - https://eips.ethereum.org/EIPS/eip-1167
36+
if bytecode.hex().startswith("0x363d3d373d3d3d363d73"):
37+
implementation_address = bytecode.hex()[22:22 + 40]
38+
return "0x" + implementation_address
39+
40+
# Minimal Proxy with receive() from 0xSplits - https://github.com/0xSplits/splits-contracts/blob/c7b741926ec9746182d0d1e2c4c2046102e5d337/contracts/libraries/Clones.sol
41+
if bytecode.hex().startswith("0x36603057343d5230"):
42+
implementation_address = bytecode.hex()[122:122 + 40]
43+
return "0x" + implementation_address
44+
45+
# 0age's minimal proxy - https://medium.com/coinmonks/the-more-minimal-proxy-5756ae08ee48
46+
if bytecode.hex().startswith("0x3d3d3d3d363d3d37363d73"):
47+
implementation_address = bytecode.hex()[24:24 + 40]
48+
return "0x" + implementation_address
49+
50+
# vyper's minimal proxy (uniswap v1) - https://etherscan.io/address/0x09cabec1ead1c0ba254b09efb3ee13841712be14#code
51+
if bytecode.hex().startswith("0x366000600037611000600036600073"):
52+
implementation_address = bytecode.hex()[32:32 + 40]
53+
return "0x" + implementation_address
54+
55+
return ""
56+
3457

3558
def resolve_contract_uri_from_address(address: str, provider: Web3) -> str:
3659
bytecode = provider.eth.get_code(address)
60+
if bytecode.hex() == "0x":
61+
raise Exception(f"Contract at '{address}' does not exist")
62+
63+
try:
64+
implementation_address = extract_minimal_proxy_implementation_address(bytecode)
65+
if implementation_address:
66+
checksum_implementation_address = provider.toChecksumAddress(implementation_address)
67+
return resolve_contract_uri_from_address(checksum_implementation_address, provider)
68+
except:
69+
pass
70+
3771
return extract_ipfs_hash_from_bytecode(bytecode)
3872

3973

thirdweb/contracts/custom.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def call(self, fn: str, *args) -> Any:
127127
f"but {len(args)} were provided.\nExpected function signature: {signature}"
128128
)
129129

130-
if func.abi["stateMutability"] == "view":
130+
if func.abi["stateMutability"] == "view" or func.abi["stateMutability"] == "pure":
131131
return func(*args).call()
132132
else:
133133
provider = self._contract_wrapper.get_provider()

0 commit comments

Comments
 (0)