what does/should msg.sender.balance return when used inside contract?

Assume we have contract A, calling B, which is calling C. msg.sender is propagated with the calls down to B and C The user is making just a single transaction i.e. no reordering is possible and no other transactions/expenses in the same block except the gas for this transaction ...

So what is the value for each of the contracts:

  1. Is it the initial balance before the call i.e. as in the previous block
  2. Is it the balance after the call i.e. after the full gas for all 3 contracts/calls is paid
  3. Is it the current amount i.e. initial balance - the gas used so far
  4. It depends on the miner code (geth, parity or ganache)

The process is the same as is independent of the client used.

Let's suppouse user A send a value val to a contract B

  • Before B execution:
    • v is substractted from A balance and added to B balance
    • gasLimit * gasPrice are substracted from A balance
  • B execution
  • After B execution
    • (gasLimit - gasUsed) * gasPrice is refunded to A
    • gasUsed * gasPrice is added to miner

There is plenty of room for misunderstanding here, so I'm going to divide this up into separate concerns.

Let us suppose Alice sends a transaction to ContractA, which calls ContractB, which calls ContractC. Let us also suppose the transaction takes 100 wei from Alice's wallet and gives it to ContractA. Finanlly, let us suppose that Alice started with 1,000 wei. Lastly, let's suppose none of the contracts have any money before we start.

It might help to have a rough approximation of the chain of contract functions in mind before we start.

contract A {
  function doSomething() public payable {
     // msg.sender.balance: 900
     // address(this).balance: 100;

contract B {
  function doSomethingElse() public {
     // address(this).balance: 0
     // msg.sender.balance: 100

contract C {
  function doLastThing() public {
    // msg.sender.balance: 0
    // address(this).balance: 0

Follow the money

  1. Alice sends 100 wei to A.doSomething(). From A's perspective, msg.sender == Alice. Alice had 1,000 but she sent 100 so now msg.sender.balance == 900.
  2. A invokes contract B.doSomethingElse(). From B's perspective, msg.sender is A, not Alice. A received 100 wei from Alice, so msg.sender.balance == 100.
  3. B invokes C. From C's perspective, msg.sender is B. B got no money from A, so msg.sender.balance == 0.
  4. A has 100, B and C have no money, and Alice has 900 wei.
  5. Alice pays transaction fee. Alice has < 900 wei left.

Hope it helps.

  • Thank you both for your answers! I am accepting Ismael's answer even Rob's one is more detailed, because as i stated 'msg.sender is propagated with the calls down to B and C', so i was looking for the same address balance status not msg.sender inside each contract.
    – KNK
    May 4 '19 at 10:36

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.