|
36 | 36 | CustomError, |
37 | 37 | DecodingError, |
38 | 38 | SignatureError, |
| 39 | + TransactionError, |
39 | 40 | ) |
40 | 41 | from ape.logging import logger |
41 | 42 | from ape.managers.config import merge_configs |
@@ -531,18 +532,28 @@ def str_to_slot(text): |
531 | 532 |
|
532 | 533 | return ProxyInfo(type=_type, target=target, abi=IMPLEMENTATION_ABI) |
533 | 534 |
|
534 | | - # safe >=1.1.0 provides `masterCopy()`, which is also stored in slot 0 |
535 | | - # call it and check that target matches |
536 | | - try: |
537 | | - singleton = ContractCall(MASTER_COPY_ABI, address)(skip_trace=True) |
| 535 | + # safe >=1.1.0 provides `masterCopy()` (0xa619486e), which is also stored in slot 0 |
| 536 | + if re.match(r".*a619486e.*", code): # NOTE: Such a short sequence can have false positives |
538 | 537 | slot_0 = self.provider.get_storage(address, 0) |
539 | | - target = self.conversion_manager.convert(slot_0[-20:], AddressType) |
540 | | - # NOTE: `target` is set in initialized proxies |
541 | | - if target != ZERO_ADDRESS and target == singleton: |
542 | | - return ProxyInfo(type=ProxyType.GnosisSafe, target=target, abi=MASTER_COPY_ABI) |
| 538 | + # Slot value is "address-like" heuristic (all contract addresses have >12 nonzero bytes) |
| 539 | + # NOTE: Farming an address with 8 leading zeros is pretty improbable |
| 540 | + if all(b == 0 for b in slot_0[:-20]) and sum(1 for b in slot_0[-20:] if b > 0) >= 12: |
| 541 | + # Slot is "address-like", so convert it |
| 542 | + target = self.conversion_manager.convert(slot_0[-20:], AddressType) |
543 | 543 |
|
544 | | - except ApeException: |
545 | | - pass |
| 544 | + try: |
| 545 | + # call `masterCopy()` and check that target matches return value |
| 546 | + singleton = ContractCall(MASTER_COPY_ABI, address)(skip_trace=True) |
| 547 | + |
| 548 | + except TransactionError: |
| 549 | + pass |
| 550 | + |
| 551 | + else: |
| 552 | + # NOTE: `target` is set in initialized proxies like GnosisSafe |
| 553 | + if target == singleton: |
| 554 | + return ProxyInfo( |
| 555 | + type=ProxyType.GnosisSafe, target=target, abi=MASTER_COPY_ABI |
| 556 | + ) |
546 | 557 |
|
547 | 558 | # eip-897 delegate proxy, read `proxyType()` and `implementation()` |
548 | 559 | # perf: only make a call when a proxyType() selector is mentioned in the code |
|
0 commit comments