2

There is a strange behaviour on user wallet balances when performing a contract call (that is supposed to have no cost). Balance is right (expected value) until a free call is requested to a contract. By debugging wallet balances it is found that wallet balances always turn into maximum value at this very moment.

Ethereum code has a suspicious line where this strange behaviuor seems to come from:

eth\api_backend.go(135):
    state.SetBalance(msg.From(), math.MaxBig256)

It belongs to GetEVM() function:

func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
    ======> state.SetBalance(msg.From(), math.MaxBig256)
        vmError := func() error { return nil }

        context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
        return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
    }

Is it there any explanation for this balance setting? Is it part of the protocol? Any hint? Thx a lot!

I read at Why does function GetEVM set the balance of from address to MaxBig256?

that this is a temporary balance setting, but I still don't get the logic behind this weird behaviour. It seems to me a messy code to avoid a lack of funds problem when calling a contract, right?

1 Answer 1

4

In Ethereum, to execute operation in EVM costs you gas. One can change any state in the blockchain which is done through making transaction. In this case, you will be charged ether. To make transaction, we have some apis like SendTransaction inside

internal/ethapi/api.go

When you do send transaction, you can set gas limit and gas price. Your balance is charged according to the operations needed to do the change.

Besides, there is an api doCall inside

internal/ethapi/api.go

This api can be called on any method. The difference between doCall and SendTransaction is - in case of doCall, no modification is persisted in the blockchain. If your solidity function returns a value, you can retrieve the value by making call to that function instead of making transaction.

So now comes to the point in the question. When doCall api is called upon a function, though it will not persist any change in the blockchain, it needs gas to temporarily execute the changes in the memory. Thus, it calls GetEVM to get the EVM from (inside)

internal/ethapi/backend.go

As this doCall will execute operations in the EVM, it temporarily needs balance in the account that has invoked doCall operation. So, the max Integer Value is temporarily set for a from account so that it can execute the operations irrespective of the its balance.

Another thing is important here, when SetBalance api is called inside

core/state/statedb.go

it just saves the change in memory. It does not persist the change in balance in the blockchain state. The change is persisted in the blockchain when a block is inserted in the chain through committing the changes saved in the memory through calling Commit function inside

core/state/statedb.go

at the time of inserting block in the chain using WriteBlockWithState api inside

core/blockchain.go

So, what comes to conclusion is- the SetBalance does not persist the balance change in the chain. As in case of doCall, it has no transactional effect. So the change in balance will never get committed in the chain.

Hope it has helped you to understand the underlying concept.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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