What msg.gas
returns is the available gas remaining for the current transaction from this point on. As each EVM instruction is executed, the EVM itself maintains a record of how much gas has been used so far and how much remains. The rules are in the Yellow Paper appendices G and H.
The EVM implements an instruction, GAS
that (from the Yellow Paper),
Get[s] the amount of available gas, including the corresponding reduction
for the cost of this instruction.
The Solidity msg.gas
construct just accesses the GAS
opcode/instruction and evaluates to the result.
When you issue a transaction to the Ethereum blockchain, one of the parameters is the amount of gas you are prepared to pay for. As the transaction gets executed, this gas amount is continually decreased as instructions are executed.
Various things can happen that affect how much gas is consumed by the transaction and how much you might get back:
There is sufficient gas; the transaction completes successfully. You (the sender of the transaction) get refunded any remaining gas.
There is insufficient gas - i.e. it runs out during execution. You get charged for all the gas, but the transaction is reverted - there is no other state change (this is an example of 4. below - running out of gas is an exceptional halting condition).
The transaction reverts (a kind of "soft" error). You get charged for gas used so far and refunded the remainder. There is no other state change (the transaction is rewound).
The transaction throws (a kind of "hard" error/exceptional halt). All the gas gets used up, you don't get a refund, and the transaction is rewound.
To answer some of your questions directly:
"Remaining" means available for rest of the execution of the current transaction.
It is neither before nor after, but during. The EVM gas counter accessed by msg.gas
is continually updated after every EVM instruction executed throughout the transaction.
Function calls within a contract are just normal EVM instruction executions. Each instruction uses gas, and the remaining gas counter is just decremented as usual. For function calls to other contracts, there is a rule that a maximum of 63/64 of the remaining gas can be passed to the function called. This is to prevent stack-depth attacks.
It gets changed just before the execution every single EVM opcode/instruction.
The remaining gas amount is managed by the EVM, and stored internally. It is accessible only via the EVM GAS
opcode, similarly to PC
, MSIZE
etc.
I hope this answers your question sufficiently.