Would `msg.sender.balance` change in a tx or a block?

Hey guys, this may or may not be directly related to the Solidity language, but it does depend on how Solidity handles the mechanism of a blockchain.

I’m trying to understand various aspects of a micro-process of a transaction such as how msg.sender’s balance is changed prior to and after a transaction is mined. Is the balance updated after a transaction is processed or after the block is mined? If two transactions request for the balance of one of the two senders, would they get the same number? To be more specific, suppose TX 1: A->B, TX 2: A->C, and in both TX 1&2, the balance of A is read as some input parameter, would it be the same for the two TXs Thanks.

In a tx. Transactions within a block have a strict order and each one works on the state as the previous transaction left it. Each transaction has the whole blockchain for its exclusive use for the short time it runs.

suppose TX 1: A->B, TX 2: A->C, and in both TX 1&2, the balance of A is read as some input parameter, would it be the same for the two TXs

There’s no parallel execution in the EVM. When TX 1 changes A to B then TX 2 will see B so it cannot do A->C. It will do B->C. But presumably it won’t just blindly overwrite it - in most cases you would read the old value first and update it.

@cameel Thanks for the explanation. “Each transaction has the whole blockchain for its exclusive use for the short time it runs.” This sentence nailed it.

The reason I raised this up is I found out msg.sender.balance is not changing within a function given below. The function gasleft() does return changing values, but not msg.sender.balance.

Since every transaction makes a state change, and msg.sender.balance is not changed within the function/transaction, it must be updated right after the transaction is finished, is that right? That means, there is a moment after finishing the previous transaction and before starting the next transaction, state variables like 'msg.sender.balance` are updated. Is this what is happening on a micro-level?

I was thinking about using msg.sender.balance as a source of randomness, so figuring out when it is changed, either at the end of, after the transaction or at the end of the block, would help a lot. Thanks.

// SPDX-License-Identifier: MIT

pragma solidity 0.8.4;

import "hardhat/console.sol";

contract Test {

    uint256 val;

    function doSth() public {
        console.logUint(msg.sender.balance);
        console.logUint(gasleft());

        for (uint256 i = 0; i < 30; i++) {
            val += i;
        }

        console.logUint(gasleft());
        console.logUint(msg.sender.balance);
    }
}

It’s not that msg.sender.balance does not get updated during a transaction. It does. If you send ether to it, you should see a difference. It’s just that you do not “buy gas as you go”. It’s deducted from balance as one lump sum before the transaction runs. And afterwards some gas may be refunded if the transaction did not actually use it all.

Also note that gas cost is not deducted from msg.sender.balance but from tx.origin.balance. These two addresses are the same inside the first function call in the transaction but if that function then calls another contract, they will be different. tx.origin is the EOA that initiated the whole transaction while msg.sender is the address (contract or EOA) that called the current function.

1 Like

Hey @cameel, this part is a bit confusing. A blockchain executes transactions linearly and “Each transaction has the whole blockchain for its exclusive use for the short time it runs.” Doesn’t that mean in the process of running through this doSth() function, no second transaction can happen? Doesn’t that also mean msg.sender.balance or tx.origin.balance would not change because of another transaction?