Skip to content

Commit

Permalink
fix: new new fields in ContractCreation response (#159)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Nov 26, 2024
1 parent 3ed074b commit 003a1d8
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
2 changes: 1 addition & 1 deletion ape_etherscan/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ def get_creation_data(self) -> list[ContractCreationResponse]:
if not isinstance(items, list):
raise ValueError("Expecting list.")

return [ContractCreationResponse(**item) for item in items]
return [ContractCreationResponse.model_validate(item) for item in items]


class AccountClient(_APIClient):
Expand Down
27 changes: 18 additions & 9 deletions ape_etherscan/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,26 @@ def get_contract_creation_receipt(
self, query: ContractCreationQuery
) -> Iterator[ContractCreation]:
client = self._client_factory.get_contract_client(query.contract)
creation_data = client.get_creation_data()
if len(creation_data) == 0:
creation_data_list = client.get_creation_data()
if len(creation_data_list) == 0:
return
elif len(creation_data) != 1:
elif len(creation_data_list) != 1:
raise ValueError("Expecting single creation data.")

receipt = self.chain_manager.get_receipt(creation_data[0].txHash)
creation_data = creation_data_list[0]
if creation_data.blockNumber is None:
# Server has an older API implementation.
# Have to look-up.
receipt = self.chain_manager.get_receipt(creation_data.txHash)
block = receipt.block_number
deployer = receipt.sender
else:
block = creation_data.blockNumber
deployer = creation_data.contractCreator

yield ContractCreation(
txn_hash=receipt.txn_hash,
block=receipt.block_number,
deployer=receipt.sender,
# factory is not implemented by this query provider
factory=None,
txn_hash=creation_data.txHash,
block=block,
deployer=deployer,
factory=creation_data.contractFactory or "",
)
11 changes: 8 additions & 3 deletions ape_etherscan/types.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import re
from dataclasses import dataclass
from typing import Union
from typing import Optional, Union

from ape.utils import cached_property
from ethpm_types import BaseModel
Expand Down Expand Up @@ -60,12 +60,17 @@ def validate_source_code(cls, value):
return value


@dataclass
class ContractCreationResponse:
class ContractCreationResponse(BaseModel):
contractAddress: str
contractCreator: str
txHash: str

# Only appears on some networks for some reason.
blockNumber: Optional[int] = None
timestamp: Optional[int] = None
contractFactory: Optional[str] = None
creationBytecode: Optional[str] = None


ResponseValue = Union[list, dict, str]

Expand Down
36 changes: 25 additions & 11 deletions tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,38 @@ def query_engine():
return ManagerAccessMixin.query_manager.engines["etherscan"]


def test_contract_creation_receipt(query_engine, mock_backend):
def test_contract_creation_metadata_query(query_engine, mock_backend):
address = "0x388C818CA8B9251b393131C08a736A67ccB19297"
creator = "0xDB65702A9b26f8a643a31a4c84b9392589e03D7c"

# Setup backend.
params = {"action": "getcontractcreation", "contractaddresses": [address]}
return_value = [
{
"contractAddress": address,
"contractCreator": creator.lower(),
"txHash": "0xd72cf25e4a5fe3677b6f9b2ae13771e02ad66f8d2419f333bb8bde3147bd4294",
}
]
mock_backend.add_handler("GET", "contract", params, return_value=return_value)
creation_data = {
"contractAddress": address,
"contractCreator": creator.lower(),
"txHash": "0xd72cf25e4a5fe3677b6f9b2ae13771e02ad66f8d2419f333bb8bde3147bd4294",
}
mock_backend.add_handler("GET", "contract", params, return_value=[creation_data])

# Perform query.
query = ContractCreationQuery(contract=address, columns=["*"])
result = list(query_engine.perform_query(query))
assert len(result) == 1
assert result[0].deployer == creator

# Newer APIs have this extra data included.
extra_data = {
"blockNumber": "14834805",
"timestamp": "1653382011",
"contractFactory": "",
"creationBytecode": "0x60c060405234801561001057600080fd5b5060405161095d38038061095d83398101604081905261002f91610107565b6001600160a01b03821661007e5760405162461bcd60e51b81526020600482015260116024820152704c49444f5f5a45524f5f4144445245535360781b60448201526064015b60405180910390fd5b6001600160a01b0381166100d45760405162461bcd60e51b815260206004820152601560248201527f54524541535552595f5a45524f5f4144445245535300000000000000000000006044820152606401610075565b6001600160a01b039182166080521660a05261013a565b80516001600160a01b038116811461010257600080fd5b919050565b6000806040838503121561011a57600080fd5b610123836100eb565b9150610131602084016100eb565b90509250929050565b60805160a0516107e361017a60003960008181609f015281816101df01526102e90152600081816101320152818161031f015261039f01526107e36000f3fe60806040526004361061004e5760003560e01c80632d2c55651461008d578063819d4cc6146100de5780638980f11f146101005780638b21f170146101205780639342c8f41461015457600080fd5b36610088576040513481527f27f12abfe35860a9a927b465bb3d4a9c23c8428174b83f278fe45ed7b4da26629060200160405180910390a1005b600080fd5b34801561009957600080fd5b506100c17f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100ea57600080fd5b506100fe6100f93660046106bb565b610182565b005b34801561010c57600080fd5b506100fe61011b3660046106bb565b61024e565b34801561012c57600080fd5b506100c17f000000000000000000000000000000000000000000000000000000000000000081565b34801561016057600080fd5b5061017461016f3660046106f3565b610312565b6040519081526020016100d5565b6040518181526001600160a01b0383169033907f6a30e6784464f0d1f4158aa4cb65ae9239b0fa87c7f2c083ee6dde44ba97b5e69060200160405180910390a36040516323b872dd60e01b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390528316906323b872dd90606401600060405180830381600087803b15801561023257600080fd5b505af1158015610246573d6000803e3d6000fd5b505050505050565b6000811161029a5760405162461bcd60e51b815260206004820152601460248201527316915493d7d49150d3d591549657d05353d5539560621b60448201526064015b60405180910390fd5b6040518181526001600160a01b0383169033907faca8fb252cde442184e5f10e0f2e6e4029e8cd7717cae63559079610702436aa9060200160405180910390a361030e6001600160a01b0383167f000000000000000000000000000000000000000000000000000000000000000083610418565b5050565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103855760405162461bcd60e51b81526020600482015260166024820152754f4e4c595f4c49444f5f43414e5f574954484452415760501b6044820152606401610291565b478281116103935780610395565b825b91508115610412577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ad509b2836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156103f857600080fd5b505af115801561040c573d6000803e3d6000fd5b50505050505b50919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261046a90849061046f565b505050565b60006104c4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166105419092919063ffffffff16565b80519091501561046a57808060200190518101906104e2919061070c565b61046a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610291565b6060610550848460008561055a565b90505b9392505050565b6060824710156105bb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610291565b843b6106095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610291565b600080866001600160a01b03168587604051610625919061075e565b60006040518083038185875af1925050503d8060008114610662576040519150601f19603f3d011682016040523d82523d6000602084013e610667565b606091505b5091509150610677828286610682565b979650505050505050565b60608315610691575081610553565b8251156106a15782518084602001fd5b8160405162461bcd60e51b8152600401610291919061077a565b600080604083850312156106ce57600080fd5b82356001600160a01b03811681146106e557600080fd5b946020939093013593505050565b60006020828403121561070557600080fd5b5035919050565b60006020828403121561071e57600080fd5b8151801515811461055357600080fd5b60005b83811015610749578181015183820152602001610731565b83811115610758576000848401525b50505050565b6000825161077081846020870161072e565b9190910192915050565b602081526000825180602084015261079981604085016020870161072e565b601f01601f1916919091016040019291505056fea2646970667358221220c0f03149dd58fa21e9bfb72a010b74b1e518d704a2d63d8cc44c0ad3a2f573da64736f6c63430008090033000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe840000000000000000000000003e40d73eb977dc6a537af587d48316fee66e9c8c", # noqa: E501
# NODE: Including made-up key to show it doesn't matter (future-proof)
"lalala": 123,
}
creation_data = {**creation_data, **extra_data}
mock_backend.add_handler("GET", "contract", params, return_value=[creation_data])

# Perform query.
query = ContractCreationQuery(contract=address, columns=["*"])
result = list(query_engine.perform_query(query))
assert len(result) == 1
assert result[0].deployer == creator
assert result[0].block == 14834805

0 comments on commit 003a1d8

Please sign in to comment.