-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
114 lines (92 loc) · 4.39 KB
/
app.py
File metadata and controls
114 lines (92 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# app.py
import os
import sys
import time
from web3 import Web3
# RPC configuration (override via environment: RPC_URL)
RPC_URL = os.getenv("RPC_URL", "https://mainnet.infura.io/v3/your_api_key")
NETWORKS = {
1: "Ethereum Mainnet",
11155111: "Sepolia Testnet",
10: "Optimism",
137: "Polygon",
42161: "Arbitrum One",
}
def network_name(chain_id: int) -> str:
return NETWORKS.get(chain_id, f"Unknown (chain ID {chain_id})")
def parse_slot(slot_str: str) -> int:
# Accept decimal or hex (e.g., "5" or "0x5")
return int(slot_str, 0)
def checksum(addr: str) -> str:
return Web3.to_checksum_address(addr)
def connect(url: str) -> Web3:
w3 = Web3(Web3.HTTPProvider(url, request_kwargs={"timeout": 30}))
if not w3.is_connected():
print("❌ Failed to connect to RPC. Check RPC_URL.")
sys.exit(1)
return w3
def get_storage_at(w3: Web3, address: str, slot: int, block_num: int) -> bytes:
return w3.eth.get_storage_at(address, slot, block_identifier=block_num)
def leaf_commitment(chain_id: int, address: str, slot: int, block_number: int, value: bytes) -> bytes:
payload = (
chain_id.to_bytes(8, "big") +
bytes.fromhex(address[2:]) +
slot.to_bytes(32, "big") +
block_number.to_bytes(8, "big") +
value.rjust(32, b"\x00")
)
return Web3.keccak(payload)
def pair_root(a: bytes, b: bytes) -> str:
first, second = (a, b) if a < b else (b, a)
return "0x" + Web3.keccak(first + second).hex()
def to_hex(b: bytes) -> str:
return "0x" + b.hex()
def main():
if len(sys.argv) != 5:
print("Usage: python app.py <contract_address> <slot(hex|int)> <block_a> <block_b>")
print("Example: python app.py 0xA0b8...eB48 0x0 18000000 19000000")
sys.exit(1)
if not Web3.is_address(sys.argv[1]): print("❌ Invalid Ethereum address."); sys.exit(1)
address = checksum(sys.argv[1])
if not Web3.is_address(address): print("❌ Invalid Ethereum address format."); sys.exit(1)
slot = parse_slot(sys.argv[2])
if slot < 0 or slot >= 2**256: print("❌ Slot out of range [0, 2^256)."); sys.exit(1)
try:
block_a = int(sys.argv[3])
block_b = int(sys.argv[4])
if block_a > block_b:
block_a, block_b = block_b, block_a
print("🔄 Swapped block order since block_a > block_b.")
except ValueError:
print("❌ block_a and block_b must be integers.")
sys.exit(1)
if block_a > block_b: block_a, block_b = block_b, block_a; print("🔄 Swapped block order for ascending comparison.")
w3 = connect(RPC_URL)
if not w3.eth.get_code(address): print("⚠️ Target has no contract code — likely an EOA, not a smart contract.")
print(f"🌐 Connected to {network_name(w3.eth.chain_id)} (chainId {w3.eth.chain_id})")
latest = w3.eth.block_number
if block_a > latest or block_b > latest: print(f"⚠️ Requested block exceeds chain tip ({latest}); values may be unavailable.")
start = time.time()
v_a = get_storage_at(w3, address, slot, block_a)
v_b = get_storage_at(w3, address, slot, block_b)
leaf_a = leaf_commitment(w3.eth.chain_id, address, slot, block_a, v_a)
leaf_b = leaf_commitment(w3.eth.chain_id, address, slot, block_b, v_b)
root = pair_root(leaf_a, leaf_b)
changed = "YES" if v_a != v_b else "NO"
print(f"🕒 A:{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(w3.eth.get_block(block_a).timestamp))} B:{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(w3.eth.get_block(block_b).timestamp))} UTC")
print("\n📦 Target")
print(f" Address: {address}")
print(f" Slot: {hex(slot)} ({slot})")
print("\n🔢 Observations")
print(f" Block A: {block_a} Value: {to_hex(v_a)} Leaf: {to_hex(leaf_a)}")
print(f" Block B: {block_b} Value: {to_hex(v_b)} Leaf: {to_hex(leaf_b)}")
print(f"\n🌳 Pair commitment (Merkle-style root over two leaves): {root}")
print(f"🔁 Value changed between blocks: {changed}")
if v_a == v_b:
print("✅ Soundness note: storage value is identical at both blocks; root binds the equality evidence.")
else:
print("ℹ️ Soundness note: values differ; root succinctly commits to both histories for independent verification.")
print(f"\n⏱️ Elapsed: {time.time() - start:.2f}s")
if __name__ == "__main__":
print(f"🕒 Observation timestamp (UTC): {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())}")
main()