[Ethereum] Why is the balance not equal to the sum of inbound, minus the sum of outbound and fees

balancesetherscanexplorersinternal-transactionstransactions

I expect to be able to calculate the balance of an account in this way: add up the value on all the incoming transactions, and subtract the value on all the outgoing transactions, then subtract all the fees paid.

When I use this method, though, I get a different balance from several other sources, like: eth.getBalance(account) and Etherscan. Why?

An Example

I picked a random account that has this "issue."

All account transactions:

Let's rewrite these transaction values…

enter image description here

in python code:

inbound = ['10']
outbound = ['9', '0.92']
paid_fees = ['0.00045932', '0.010846898028', '0.00084084']

Account Balance:

So when we calculate the sum, I expect to get the same as the balance that Etherscan shows:

enter image description here

Instead, I get Decimal('0.067852941972') from the following calculation:

from web3 import Web3

total = sum(Web3.toWei(income, 'ether') for income in inbound)
for ether_spent in outbound + paid_fees:
    total -= Web3.toWei(ether_spent, 'ether')

total_ether = Web3.fromWei(total, 'ether')
print(total_ether)

What is this dark magic?

Did this account generate Ether out of thin air?

Best Answer

Did this account generate Ether out of thin air?

No. Ethereum isn't broken, and neither are ENS or Etherscan. Although Etherscan could be clearer about what's happening here.

So how do you get the real balance?

If you click into the most recent transaction issued by the account (the one with 0 outbound value), you see this:

enter image description here

Sorry it's awkwardly clipped. I'm trying to give a bit of privacy to this random person.

The first and third TRANSFER are being sent back to the account that issued the transaction. Although it's an outbound transaction, with 0 value, the account actually got Ether back! So what is the new balance?

from decimal import Decimal
real_ether_balance = total_ether + Decimal('0.02') + Decimal('0.0045')

The real balance is: Decimal('0.09235')

Sweet, everything adds up again!

But I have this problem, and I haven't sent or received any transactions

"Internal transactions" is the way Etherscan refers to it when a contract sends ether somewhere. Any contract can issue "internal transactions" (really just sending ether) when it is run. The contract can send it to any account.

So an account with zero inbound and zero outbound transactions can still have a balance.

How?

Let's say account Alice has no transactions in or out. Account Betty can send a transaction that executes a function on contract Carly. During execution, contract Carly can "send" ether to account Alice. This does not issue a new transaction, it just increases Alice's balance and decreases Carly's balance.

Related Topic