Ich versuche, Änderungen des Kontospeichers abzuleiten, indem ich Konten (hier stellen die Konten die Schlüsseladresse in der ERC20-Saldenzuordnungszuordnung (Adresse => uint256) ) ihren entsprechenden Speicherschlüsseln aus einer Paritätstransaktionsverfolgung zu.
Ein Beispiel-Trace (abgerufen über web3.py) der Transaktion https://etherscan.io/tx/0x210cfe3d3b62f415ed0327a3c6177086df4937b6280031255360b6d137308554 ist:
{
'output': '0x',
'stateDiff': {
'0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5': {
'balance': {
'*': {
'from': '0x122291885d6222bc5ec',
'to': '0x12229193ca3f58565ec'
}
},
'code': '=',
'nonce': '=',
'storage': {}
},
'0xaddba95f769b5d42c02e144102817eab9d00efd3': {
'balance': '=',
'code': '=',
'nonce': '=',
'storage': {
'0x1ded6755a6d7d843883da8cd8948931cf9f8b1e8f8983ad77e1685ece0b92fc2': {
'*': {
'from': '0x0000000000000000000000000000000000000000000000000000000000000000',
'to': '0x000000000000000000000000000000000000000000000000000bfb8d0ebc5000'
}
},
'0x5020d77d5345022a5466af6f78731b10f92d31e17961c23ea6ce5c185dc75d49': {
'*': {
'from': '0x0000000000000000000000000000000000000000000000000000000000000000',
'to': '0x0000000000000000000000000000000000000000000000000000e1412a5f1c00'
}
}
}
},
'0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40': {
'balance': {
'*': {
'from': '0x2c4c7111f4801a8',
'to': '0x2c410434bee61a8'
}
},
'code': '=',
'nonce': {
'*': {
'from': '0x143',
'to': '0x144'
}
},
'storage': {}
}
},
'trace': [{
'action': {
'callType': 'call',
'from': '0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40',
'gas': '0x9008',
'input': '0xa9059cbb000000000000000000000000e034e561ce112c5f261f15d447e8f2436d9625040000000000000000000000000000000000000000000000000000e130de0be000',
'to': '0xaddba95f769b5d42c02e144102817eab9d00efd3',
'value': '0x0'
},
'result': {
'gasUsed': '0x3924',
'output': '0x'
},
'subtraces': 0,
'traceAddress': [],
'type': 'call'
}],
'vmTrace': None
}
Laut https://solidity.readthedocs.io/en/v0.4.24/miscellaneous.html#layout-of-state-variables-in-storage befindet sich „der Wert, der einem Zuordnungsschlüssel k entspricht, unter keccak256(k . p ) wobei . eine Verkettung ist". Das notwendige linke Pad ist mir laut "keccack(LeftPad32(key, 0), LeftPad32(map position, 0))" https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat bekannt . obwohl die Hash-Funktionen dies bereits intern zu handhaben scheinen.
Ich habe Web3.sha3() für diesen keccak256-Speicherschlüssel ausprobiert, und andere Probleme bei StackOverflow erwähnen, dass Solidity einen etwas anderen Hash-Algorithmus verwendet. Nevertheless, also by using the proper Web3.soliditySha3() I do not arrive at a hash that would present me the key found in the the trace (here, 0x1ded6755a6d7d843883da8cd8948931cf9f8b1e8f8983ad77e1685ece0b92fc2 or 0x5020d77d5345022a5466af6f78731b10f92d31e17961c23ea6ce5c185dc75d49 ) to the account 0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40 .
Was ist der richtige Weg (vorzugsweise mit web3.py), um das Konto und die Position zu hashen, um zum Mapping-Speicherschlüssel zu gelangen?
Wie von @jaime in den Kommentaren erwähnt, benötigen Sie die position
der Zuordnungsvariablen, um die Beziehung zwischen address
und zu finden storage key
.
Unten finden Sie einen Code, den ich geschrieben habe, um den position
für einen einfachen erc20-Vertrag zu erkennen (unter Verwendung von web3.py):
import json
from web3.auto.infura import w3
from eth_utils import remove_0x_prefix, to_int, to_checksum_address, to_hex
# erc20 contract address
CONTRACT_ADDRESS = '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7'
# address with non zero token balance
HOLDER_ADDRESS = '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb'
def getStorageAtIndex(i):
pos = str(i).rjust(64, '0')
key = remove_0x_prefix(HOLDER_ADDRESS).rjust(64, '0').lower()
storage_key = to_hex(w3.sha3(hexstr=key + pos))
return to_int(w3.eth.getStorageAt(CONTRACT_ADDRESS, storage_key))
for i in range(0, 20):
if getStorageAtIndex(i) != 0:
print("position is {}".format(i))
Ergebnis:
>>> position is 5
Sobald Sie den korrekten Positionswert haben, können Sie die im Vertrag gespeicherten Werte einfach abrufen.
pos = str(5).rjust(64, '0')
key = remove_0x_prefix(HOLDER_ADDRESS).rjust(64, '0').lower()
storage_key = to_hex(w3.sha3(hexstr=key + pos))
w3.eth.getStorageAt(CONTRACT_ADDRESS, storage_key)
Jaime
Daniel