Skip to content

Commit

Permalink
Merge branch 'main' into perf/logging-load
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Dec 11, 2024
2 parents 4f69acb + f924acf commit a8c0228
Show file tree
Hide file tree
Showing 20 changed files with 2,013 additions and 57 deletions.
32 changes: 24 additions & 8 deletions src/ape/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
from inspect import getframeinfo, stack
from pathlib import Path
from types import CodeType, TracebackType
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast
from typing import TYPE_CHECKING, Any, Callable, Optional, Union

import click
from eth_typing import Hash32, HexStr
from eth_utils import humanize_hash, to_hex
from rich import print as rich_print

from ape.logging import LogLevel, logger

if TYPE_CHECKING:
from eth_typing import HexStr
from ethpm_types.abi import ConstructorABI, ErrorABI, MethodABI
from ethpm_types.contract_type import ContractType

Expand Down Expand Up @@ -521,9 +520,11 @@ class BlockNotFoundError(ProviderError):

def __init__(self, block_id: "BlockID", reason: Optional[str] = None):
if isinstance(block_id, bytes):
block_id_str = to_hex(block_id)
block_id_str = block_id.hex()
if not block_id_str.startswith("0x"):
block_id_str = f"0x{block_id_str}"
else:
block_id_str = HexStr(str(block_id))
block_id_str: "HexStr" = f"{block_id}" # type: ignore

message = (
"Missing latest block."
Expand Down Expand Up @@ -621,11 +622,26 @@ class UnknownSnapshotError(ChainError):
"""

def __init__(self, snapshot_id: "SnapshotID"):
snapshot_id_str: str
if isinstance(snapshot_id, bytes):
# Is block hash
snapshot_id = humanize_hash(cast(Hash32, snapshot_id))
# Is block hash. Logic borrowed from `eth_utils.humanize_hash()`.
if len(snapshot_id) <= 5:
snapshot_id_str = snapshot_id.hex()
else:
value_hex = snapshot_id.hex()
head = value_hex[:4]
tail_idx = -1 * 4
tail = value_hex[tail_idx:]
snapshot_id_str = f"{head}..{tail}"

snapshot_id_str = (
f"0x{snapshot_id_str}" if not snapshot_id_str.startswith("0x") else snapshot_id_str
)

else:
snapshot_id_str = f"{snapshot_id}" # type: ignore

super().__init__(f"Unknown snapshot ID '{snapshot_id}'.")
super().__init__(f"Unknown snapshot ID '{snapshot_id_str}'.")


class QueryEngineError(ApeException):
Expand Down
6 changes: 5 additions & 1 deletion src/ape/managers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
)
from ape.utils.misc import log_instead_of_fail
from ape.utils.os import create_tempdir, in_tempdir
from ape.utils.rpc import RPCHeaders
from ape.utils.rpc import USER_AGENT, RPCHeaders

if TYPE_CHECKING:
from ethpm_types import PackageManifest
Expand All @@ -39,6 +39,10 @@ def __init__(self, data_folder: Optional[Path] = None, request_header: Optional[
else:
self.DATA_FOLDER = data_folder or Path.home() / ".ape"

request_header = request_header or {
"User-Agent": USER_AGENT,
"Content-Type": "application/json",
}
self.REQUEST_HEADER = request_header or {}

def __ape_extra_attributes__(self):
Expand Down
5 changes: 1 addition & 4 deletions src/ape/utils/basemodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from ape.exceptions import ApeAttributeError, ApeIndexError, ProviderNotConnectedError
from ape.logging import logger
from ape.utils.misc import log_instead_of_fail, raises_not_implemented
from ape.utils.rpc import USER_AGENT

if TYPE_CHECKING:
from pydantic.main import Model
Expand Down Expand Up @@ -173,9 +172,7 @@ def config_manager(cls) -> "ConfigManager":
The :class:`~ape.managers.config.ConfigManager`.
"""
config = import_module("ape.managers.config")
return config.ConfigManager(
request_header={"User-Agent": USER_AGENT, "Content-Type": "application/json"},
)
return config.ConfigManager()

@manager_access
def conversion_manager(cls) -> "ConversionManager":
Expand Down
22 changes: 10 additions & 12 deletions src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,18 +518,16 @@ def str_to_slot(text):
return ProxyInfo(type=_type, target=target)

# safe >=1.1.0 provides `masterCopy()`, which is also stored in slot 0
# detect safe-specific bytecode of push32 keccak256("masterCopy()")
safe_pattern = b"\x7f" + keccak(text="masterCopy()")[:4] + bytes(28)
if to_hex(safe_pattern) in code:
try:
singleton = ContractCall(MASTER_COPY_ABI, address)(skip_trace=True)
slot_0 = self.provider.get_storage(address, 0)
target = self.conversion_manager.convert(slot_0[-20:], AddressType)
# NOTE: `target` is set in initialized proxies
if target != ZERO_ADDRESS and target == singleton:
return ProxyInfo(type=ProxyType.GnosisSafe, target=target)
except ApeException:
pass
# call it and check that target matches
try:
singleton = ContractCall(MASTER_COPY_ABI, address)(skip_trace=True)
slot_0 = self.provider.get_storage(address, 0)
target = self.conversion_manager.convert(slot_0[-20:], AddressType)
# NOTE: `target` is set in initialized proxies
if target != ZERO_ADDRESS and target == singleton:
return ProxyInfo(type=ProxyType.GnosisSafe, target=target)
except ApeException:
pass

# eip-897 delegate proxy, read `proxyType()` and `implementation()`
# perf: only make a call when a proxyType() selector is mentioned in the code
Expand Down
138 changes: 137 additions & 1 deletion tests/functional/data/contracts/ethereum/local/BeaconProxy.json

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions tests/functional/data/contracts/ethereum/local/ERCProxy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"abi": [
{
"inputs": [],
"name": "proxyType",
"outputs": [
{
"name": "proxyTypeId",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "implementation",
"outputs": [
{
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"name": "_target",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
}
],
"contractName": "ERCProxy",
"deploymentBytecode": {
"bytecode": "0x608060405234801561001057600080fd5b5060405160208061014a833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905560f9806100516000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634555d5c98114604d5780635c60da1b146071575b600080fd5b348015605857600080fd5b50605f60ac565b60408051918252519081900360200190f35b348015607c57600080fd5b50608360b1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b600190565b60005473ffffffffffffffffffffffffffffffffffffffff16905600a165627a7a72305820ae971f5c593cbaf95a4ff9c244af7a9afd16cda9faff299ef9f50e1953626a340029"
},
"devdoc": {
"methods": {}
},
"methodIdentifiers": {
"implementation()": "0x5c60da1b",
"proxyType()": "0x4555d5c9"
},
"runtimeBytecode": {
"bytecode": "0x60806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634555d5c98114604d5780635c60da1b146071575b600080fd5b348015605857600080fd5b50605f60ac565b60408051918252519081900360200190f35b348015607c57600080fd5b50608360b1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b600190565b60005473ffffffffffffffffffffffffffffffffffffffff16905600a165627a7a72305820ae971f5c593cbaf95a4ff9c244af7a9afd16cda9faff299ef9f50e1953626a340029"
},
"sourceId": "tests/functional/data/sources/DelegateProxy.sol",
"sourcemap": "27:278:0:-;;;77:56;8:9:-1;5:2;;;30:1;27;20:12;5:2;77:56:0;;;;;;;;;;;;;112:6;:16;;-1:-1:-1;;;;;112:16:0;;;-1:-1:-1;;;;;;112:16:0;;;;;;;;;27:278;;;;;;",
"userdoc": {
"methods": {}
}
}
Loading

0 comments on commit a8c0228

Please sign in to comment.