# Development Update 1 ~ [8/10/2021] The following is the first development update for the selected project "Removal of gas stipend for `CALL` opcodes". It provides a low-level description of how the Geth client executes the `CALL` opcode. This understanding would be critical for realizing the impact of removing the gas stipend on contracts relying on it and the EVM execution of transactions. ## Description ### Usage of Gas Stipend In Solidity, value can be transferred between smart contracts via the methods - `.send()`, `.transfer()`, and `.call()`. When called, the fallback function of the recipient contract receives a certain amount of gas for the execution of code. The amount of gas forwarded depends on the method used by the sender contract. If `.send()` or `.transfer()` is called, the recipient only receives a gas stipend of 2300 in which it can perform limited computation such as issuing a log. This amount is insufficient to execute operations that involve making changes to the storage. If `.call()` is used, however, all the remaining gas in the sender contract is forwarded in addition to the gas stipend. While this can potentially be a security risk for a reentrancy attack, there is an option to limit the amount of gas forwarded using `.call{gas: 3000}`. ### Client Execution of CALL opcode When a transaction is sent to a Geth client using `.transfer()`, `.send()` or `call`, the `Run` function in *interpreter.go* is called. This function iterates over the contract's bytecode and executes the operations associated with the instructions. The bytecode is stored in a byte array, where each element is an instruction that can be interpreted by the EVM. Below is an example of such an array for the contract *[receiveEther.sol](https://github.com/uink45/Gas-Stipend-Smart-Contract/blob/main/ReceiveEther.sol)*: **[96 128 96 64 82 52 128 21 97 0 16 87 96 0 128 253 91 80 96 187 128 97 0 31 96 0 57 96 0 243 254 96 128 96 64 82 96 4 54 16 96 31 87 96 0 53 96 224 28 128 99 18 6 95 224 20 96 39 87 96 37 86 91 54 96 37 87 0 91 0 91 52 128 21 96 50 87 96 0 128 253 91 80 96 57 96 77 86 91 96 64 81 96 68 145 144 96 108 86 91 96 64 81 128 145 3 144 243 91 96 0 71 144 80 144 86 91 96 0 129 144 80 145 144 80 86 91 96 102 129 96 85 86 91 130 82 80 80 86 91 96 0 96 32 130 1 144 80 96 127 96 0 131 1 132 96 95 86 91 146 145 80 80 86 254 162 100 105 112 102 115 88 34 18 32 136 58 136 35 217 73 72 128 143 201 43 213 20 70 47 22 56 164 61 154 225 73 45 75 203 232 7 52 126 35 38 195 100 115 111 108 99 67 0 8 9 0 51]** The EVM uses the program counter as the array's index for accessing instructions. The counter is incremented by one for all opcodes, except for `JUMP`, `JUMPI` and those that belong to the `PUSH` family. The reason is that instructions for `PUSH` opcodes are specified in multiple bytes instead of single. For example, the first two elements **96** and **128** in the array above will be interpreted as `PUSH 80`, and the counter would be incremented by two. During the transaction's execution, when it retrieves the instruction `241`, it is used as a key for the mapping `OpCode` for getting the corresponding value `CALL`. This opcode is later used to get the associated operation from the `JumpTable`. As declared in *jump_table.go*, an operation is a struct that consists of the following variables: ``` type operation struct { // execute is the operation function execute executionFunc constantGas uint64 dynamicGas gasFunc // minStack tells how many stack items are required minStack int // maxStack specifies the max length the stack can have for this operation // to not overflow the stack. maxStack int // memorySize returns the memory size required for the operation memorySize memorySizeFunc halts bool // indicates whether the operation should halt further execution jumps bool // indicates whether the program counter should not increment writes bool // determines whether this a state modifying operation reverts bool // determines whether the operation reverts state (implicitly halts) returns bool // determines whether the operations sets the return data content } ``` Before executing the operation, it performs multiple checks to ensure that the amount of available gas is greater than `constantGas`, the stack's current is length is between the range of `minStack` and `maxStack`, and the change in memory's size does not cause an overflow. By implementing `Println(operation)` in the source code, the details about the operation associated with `CALL` can be seen below: | variable | value | | -------- | -------- | | execute | 0x7ff66061cfc0 | | constantGas | 100 | | dynamicGas | 0x7ff66062a020 | | minStack | 7 | | maxStack | 1030 | | memorySize | 0x7ff660628ae0 | | halts | false | | jumps | false | | writes | false | | reverts | false | | returns | true | Here, **execute** references to the function `opCall` that is implemented in *instructions.go* and **dynamicGas** references to the `gasCall` function. Furthermore, `memorySize` is calculated using `memorySizeFunc`. Upon executing `opCall`, the `CallStipend` is added to the `gas` variable only if the value being transferred is not equal to 0, . The purpose of this check is to allow the receiving contract to issue a log as a confirmation for receiving the funds. After the condition has been checked, it calls the `Call` function that ultimately applies the changes to `StateDB`, involving subtracting the sender's balance and adding to the receiver's balance by an equal amount. ## Next Step With the help of this knowledge, the next step would be to experiment with Geth by modifying the source code (i.e. changing the value of gas stipend) and running a private build. The impact of these changes will be documented and explained in the next update. ## Links 1. https://ethereum.stackexchange.com/questions/19341/address-send-vs-address-transfer-best-practice-usage/38642#38642 2. https://github.com/ethereum/go-ethereum/blob/633e7ef4781453111c4b29e14a65c5335bb9ecac/core/vm/jump_table.go#L30 3. https://github.com/ethereum/go-ethereum/blob/master/core/vm/instructions.go 4. https://github.com/ethereum/go-ethereum/blob/633e7ef4781453111c4b29e14a65c5335bb9ecac/core/evm.go#L116 5. https://github.com/ethereum/go-ethereum/blob/633e7ef4781453111c4b29e14a65c5335bb9ecac/core/vm/interpreter.go ###### tags: `CDAP`