1

when I get ethereum block data like below...

from web3 import Web3

w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
print(w3.isConnected()) 

block = w3.eth.get_block('latest')

it can get block data and transaction list.

block data

'difficulty': 17179869184, 
'extraData': HexBytes('0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa'), 
'gasLimit': 5000, 
'gasUsed': 0, 
'hash': HexBytes('0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'), 
'logsBloom': 
HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'), 
'miner': '0x0000000000000000000000000000000000000000', 
'mixHash': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000'), 
'nonce': HexBytes('0x0000000000000042'),
'number': 0, 
'parentHash': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000000'), 
'sha3Uncles': HexBytes('0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'), 
'size': 540, 
'timestamp': 0, 
'totalDifficulty': 17179869184, 
'transactions': [], 
'stateRoot': HexBytes('0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544'), 
'transactionsRoot':
HexBytes('0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'), 
'receiptsRoot': HexBytes('0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'), 
'uncles': []

transaction data

{
'blockHash': HexBytes('0x1082201478339f0f261c239525d5f03cc6be028fd3617c1d2399369348483104'), 
'blockNumber': 12873549, 
'from': '0x21a31Ee1afC51d94C2eFcCAa2092aD1028285549', 
'gas': 207128, 'gasPrice': 32000000000, 
'hash': HexBytes('0x67835376671cc657d32bc042c073c8b94ad38384632a93b9c6d096b5e9d54ba7'), 
'input': '0x', 
'nonce': 766127, 
'to': '0x7FA543BA34C58e65A9dEa435dCD7184864cabd06', 
'transactionIndex': 36, 
'value': 197771640000000000, 
'type': '0x0', 
'v': 38, 
'r': HexBytes('0xc16685957b794254f00301485d9629a6e5ac023233c28f581e5b06437a969b56'), 
's': HexBytes('0x06cd843d606ff26b583ed3b6d93072ef46f23f756e6eef7cfe8b8ffd2e52a873')
}

I have the following questions...:

  1. From a transaction, is there a way to know if the address of to or from is EOA (External Owned Account) or CA (Contract Account)?
  2. If it is a CA, can I get the ABI of the contract through web3py?
  3. If a token is sent from A to B through a contract, how is the balance of each token of A and B stored? Is it stored in ethereum EOA? (ex USDT)
  4. As shown in the figure below, when a transaction occurs, the state seems to change. Can I get this latest state data?(I wonder what data is in the state...)

enter image description here

Sorry for the many questions...

If there is an alternative other than web3 to solve the above problem, please let me know, thank you!

1

A1: yes you can know if an address is a contract or an EOA. contracts have bytecode stored on the blockchain but EOA doesn't. getCode(address) will return the bytecode. if it returns 0x0 then it's an EOA.

A2: You can't get the abi of a contract via Web3.py meaning from an RPC endpoint. Abis are shared externally. Although all Tokens should have a minimum ABi like an ERC20 or BEP20 (for bsc)

A3: the balances of tokens are not stored the same way as the balances of ether. the token balances are just an uint256 number linked to an address and they are stored in the token contract itself usually in a mapping of this kind : mapping(address => uint256) public balances;. the transfer functions only edit that mapping for each address.

A4: The state changes can be anything related to the blockchain including ether balances, smart contract creations, smart contract transactions, etc. getting those states in their raw format would require getting the data from the local database of a full node. But you can still trace every transaction in new blocks to get all its interactions whether in terms of transactions and calls or even in the lowest operations level.

If you are trying to get the state of a certain contract you can subscribe to new transactions and filter by the exact contract and peep into it's data. If the contract uses logs, you can subscribe to those instead and map every logged interaction into a timeline of events.

2
  • Thank you so much for replying! I have an additional question...! When I checked, it seems that only the latest balance can be checked through the address. In the Etherscan site, I can check the transaction history of a specific address. Is there a way to get this history? Or... In the case of etherscan, is it recording the entire history from block 0? example site address contract
    – Minwoo
    Jul 27 at 1:11
  • @Minwoo you cna use the block identifier to the the data from a specific block : check here ethereum.stackexchange.com/a/103818/25049 Jul 28 at 19:07
1
  1. You can find if an address is a contract by fetching its bytecode : web3.eth.get_code(address). If it has any, then it's a smart contract, otherwise it's EOA. (Web3py ref)
  2. You cannot retrieve the ABI of a contract throught web3py, and more globally, you just cannot retrieve the ABI of a contract if it was not published (you can retrieve the number and type of parameters you must pass to methods if you reverse engineer the contract but you won't know what the methods or the parameters are for). This being said, you can identify an ERC20 implementation by checking if it implements certain methods. Because ERC20 is a standard, you can use the ERC20 ABI to read and send transactions to any ERC20 contract.
  3. The balance is stored in a mapping in the ERC20 (token) smart contract. For example, from openzeppelin ERC20 implementation, it is stored in the _balances mapping mapping(address => uint256) private _balances; If a token is sent from A to B, the ERC20 smart contract will substract the amount from _balances[A] and add it to _balances[B]. If B doesn't have any, it will create the mapping.
  4. Different kind of nodes exist : full node and archive node.
    • full node only store the latest state of smart contracts. The state of a smart contract is the last value of its variables. It means that if we are at State', you won't be able to retrieve the balance of user A at State.
    • archive node store all the states of a smart contracts. It means that if the state of a smart contract change, it will update its state and save a copy of the previous state. You can retrieve the state at a specific block my specifying in which block you want to make your call : myERC20Contract.methods.balanceOf(walletAddress).call(undefined, blockNumber, callback)
1
  • Thank you so much for replying! I have an additional question...! When I checked, it seems that only the latest balance can be checked through the address. In the Etherscan site, I can check the transaction history of a specific address. Is there a way to get this history? Or... In the case of etherscan, is it recording the entire history from block 0? example site address contract
    – Minwoo
    Jul 26 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.