{"id":15065155,"url":"https://github.com/mtumilowicz/ethereum-gas-workshop","last_synced_at":"2025-04-14T23:42:30.762Z","repository":{"id":197870597,"uuid":"698556273","full_name":"mtumilowicz/ethereum-gas-workshop","owner":"mtumilowicz","description":"Introduction to EMV, gas pricing model and standard gas optimisation techniques.","archived":false,"fork":false,"pushed_at":"2024-03-19T23:27:23.000Z","size":95,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-14T23:42:15.145Z","etag":null,"topics":["blockchain","cryptocurrency","ethereum","ethereum-contract","ethereum-gas-prices","ethereum-smart-contract","ethereum-virtual-machine","solidity","solidity-contracts","solidity-language","workshop","workshop-material","workshop-materials","workshops"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtumilowicz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-30T09:10:06.000Z","updated_at":"2024-11-13T22:58:06.000Z","dependencies_parsed_at":"2024-11-21T22:15:35.706Z","dependency_job_id":null,"html_url":"https://github.com/mtumilowicz/ethereum-gas-workshop","commit_stats":null,"previous_names":["mtumilowicz/ethereum-gas-fee-workshop","mtumilowicz/ethereum-gas-workshop"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fethereum-gas-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fethereum-gas-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fethereum-gas-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fethereum-gas-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtumilowicz","download_url":"https://codeload.github.com/mtumilowicz/ethereum-gas-workshop/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248981259,"owners_count":21193143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","cryptocurrency","ethereum","ethereum-contract","ethereum-gas-prices","ethereum-smart-contract","ethereum-virtual-machine","solidity","solidity-contracts","solidity-language","workshop","workshop-material","workshop-materials","workshops"],"created_at":"2024-09-25T00:34:46.207Z","updated_at":"2025-04-14T23:42:30.741Z","avatar_url":"https://github.com/mtumilowicz.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ethereum-gas-workshop\n\n* references\n    * https://www.oreilly.com/library/view/hands-on-smart-contract/9781492045250/\n    * https://www.amazon.com/Solidity-Programming-Essentials-building-contracts/dp/1803231181\n    * https://www.amazon.com/Beginning-Ethereum-Smart-Contracts-Programming/dp/1484292707\n    * https://www.springerprofessional.de/en/ethereum-smart-contract-development-in-solidity/18334966\n    * https://www.manning.com/books/blockchain-in-action\n    * https://www.packtpub.com/product/mastering-blockchain-programming-with-solidity/9781839218262\n    * https://ethereum.stackexchange.com/questions/594/how-do-gas-refunds-work\n    * https://ethereum.stackexchange.com/questions/92965/how-are-gas-refunds-payed\n    * https://ethereum.stackexchange.com/questions/125028/is-there-still-gas-refund-for-sstore-to-0-instructions\n    * https://ethereum.stackexchange.com/questions/3/what-is-meant-by-the-term-gas\n    * https://ethereum.stackexchange.com/questions/872/what-is-the-cost-to-store-1kb-10kb-100kb-worth-of-data-into-the-ethereum-block\n    * https://medium.com/@eiki1212/what-is-ethereum-gas-simple-explanation-2f0ae62ed69c\n    * https://ethereum.stackexchange.com/questions/133284/how-to-see-the-refund-of-selfdestruct\n    * https://ethereum.stackexchange.com/questions/15114/if-all-nodes-execute-smart-contracts-why-do-only-block-creators-get-the-gas-fee\n    * https://www.blocknative.com/blog/ethereum-transaction-gas-limit\n    * https://medium.com/coinmonks/a-short-guide-to-ethereum-gas-fees-5c4c53a05feb\n    * https://help.coinbase.com/en/coinbase/getting-started/crypto-education/eip-1559\n    * https://medium.com/monolith/understanding-defi-ethereums-eip-1559-update-explained-a424416cbf69\n    * https://medium.com/@eric.conner/fixing-the-ethereum-fee-market-eip-1559-9109f1c1814b\n    * https://medium.com/@TrustlessState/eip-1559-the-final-puzzle-piece-to-ethereums-monetary-policy-58802ab28a27\n    * https://consensys.net/blog/quorum/what-is-eip-1559-how-will-it-change-ethereum/\n    * https://medium.com/coinmonks/learn-evm-in-depth-1-the-evm-bytecode-and-environment-b751c431f020\n    * https://ethereum.org/en/developers/docs/evm/\n    * https://blog.qtum.org/the-ethereum-virtual-machine-def21fdc8953\n    * https://medium.com/@danielyamagata/understand-evm-opcodes-write-better-smart-contracts-e64f017b619\n    * https://www.cryptopolitan.com/solidity-gas-optimization-strategies/\n    * https://www.alchemy.com/overviews/solidity-gas-optimization\n    * https://certik.medium.com/gas-optimization-in-ethereum-smart-contracts-10-best-practices-cbd57548bdf0\n    * https://yamenmerhi.medium.com/gas-optimization-in-solidity-75945e12322f\n    * https://betterprogramming.pub/solidity-gas-optimizations-and-tricks-2bcee0f9f1f2\n    * https://www.rareskills.io/post/gas-optimization\n    * https://coinsbench.com/comprehensive-guide-tips-and-tricks-for-gas-optimization-in-solidity-5380db734404\n    * https://ethereum.stackexchange.com/questions/7949/why-do-constant-state-variables-get-initialised-every-time\n    * https://ethereum.stackexchange.com/questions/141988/can-gas-refunds-for-deleted-storage-be-used-as-transient-storage\n    * https://ethereum.stackexchange.com/questions/68529/solidity-modifiers-in-library\n    * https://medium.com/@Ground_Zero/ethereum-l2-solutions-vs-rollups-understanding-the-difference-a93f5108bac5\n    * https://medium.com/@0xegormajj/layer-2-ethereum-scaling-solutions-for-a-faster-and-more-efficient-network-9b1e9fea775e\n    * https://kbaiiitmk.medium.com/scaling-the-ethereum-using-rollups-layer-2-a9b488ca2fe\n    * https://medium.com/@amdeviprasad/exploring-layer-2-solutions-from-plasma-framework-to-rollups-df4a9647f587\n    * https://medium.com/coinmonks/zk-rollup-optimistic-rollup-70c01295231b\n    * https://medium.com/ppio/zk-rollup-making-scalable-blockchains-possible-7308b695d929\n    * https://medium.com/taipei-ethereum-meetup/reason-why-you-should-use-eip1167-proxy-contract-with-tutorial-cbb776d98e53\n\n## preface\n* goals of this workshop\n    * introduction to EMV\n    * understanding gas pricing model\n    * showing standard gas optimisation techniques\n* workshop task\n    * improve `Inefficient.sol`\n        1. replace `compareStrings` with `keccak256`\n        1. use correct qualifiers: view, calldata, etc\n        1. use correct data structure: mapping\n\n## EVM = Ethereum Virtual Machine\n* refresh: virtual machine\n    * is a type of simulation of a CPU\n    * has predefined operations, but such operations must be understood by the virtual machine and not by the CPU\n    * is a program capable of interpreting a specific language\n        * transforming (indirectly) this language into machine language\n        * executing what needs to be executed on the CPU.\n    * language that the virtual machine understands is called bytecode\n        * each virtual machine has its own bytecode with its own definitions\n        * bytecode is a series of instructions that the EVM will interpret and execute\n        * when we write a smart contract in Solidity or Vyper, the result must be transformed (compiled) to bytecode\n        * EVM bytecode is not machine language\n            * although it looks like a set of bits, it is only a representation\n* Ethereum is like a single-threaded computer\n    * it can process one transaction at a time\n    * Sharding of blockchain would improve it and make it like a multithreaded computer\n* virtual, isolated environment where code (smart contracts) can be executed\n    * running on the EVM is not directly executed by any single computer, but by all nodes in the Ethereum network\n    * you can think of JVM(Java Virtual Machine) as the same mechanism\n* is Turing complete\n    * contracts contain very little code and their methods require very few instructions to execute\n        * usually less than one thousand\n        * regular computers execute several billion instructions per second\n    * to prevent infinite loops and resource exhaustion, the EVM requires users to pay for computation and storage\n        * Ethereum Virtual Machine is seen only as quasi-Turing complete\n        * payment is made in the form of \"gas\"\n            * a unit of measurement for the amount of computational work required to execute operations\n        * since the London hard fork, each block has a target size of 15 million units of gas\n            * the actual size of a block will vary depending on network demand\n                * protocol achieves an equilibrium block size of 15 million on average through the process of tâtonnement\n                * if the block size is greater than the target block size, the protocol will increase the base fee for the following block\n                * the protocol will decrease the base fee if the block size is less than the target block size\n                * maximum size: 30 million gas (2x the target block size)\n                    * means that a block can only contain transactions which cost 30m gas to execute\n        * example\n            * 3m gas is at maximum 1.5 million instructions (in a very theoretical, unrealistic scenario)\n                * example\n                    * MSTORE (Memory Store): around 3 gas\n                    * SSTORE (Storage Operation):\n                        * writing to a new storage slot: Around 20,000 gas (for a 256 bit word)\n                            * a kilobyte is thus 640k gas\n                                * so if gas ~ 10 gwei\n                                * 1KB costs 0.0064 ETH\n                                * 1GB costs 6400 eth (for eth 1.5k USD, ~ 12,000,000 USD)\n                            * so a block can only contain instructions that write to storage about 150 times\n                        * updating an existing storage slot: Around 5,000 gas\n                    * SLOAD (Storage Load): around 200 gas\n* is deterministic\n    * running the same code with the same inputs will produce the same results every time\n* is a stack-based machine\n* operates using a set of instructions called \"opcodes\"\n    * opcodes are predefined instructions that the EVM interprets\n    * some operators have operands, but not all\n        * operator that have operand: PUSH\n            * push to the stack\n        * operator that does not have: ADD\n            * takes from the stack, add and push result\n    * example\n        ```\n        // Solidity code\n        function addIntsInMemory(uint a, uint b) public pure returns (uint) {\n            uint result = a + b;\n            return result;\n        }\n        ```\n        is compiled into operands and operators (opcodes)\n        ```\n        PUSH1 0x20      // Load the memory slot size (32 bytes)\n        MLOAD           // Load 'a' from memory\n        PUSH1 0x40      // Load the memory slot size (32 bytes)\n        ADD             // Add 'a' and 'b'\n        MSTORE          // Store the result back in memory\n        ```\n    * then it is interpreted to bytecode\n* bytecode is a set of bytes that must be executed in order, from left to right\n    * each byte can be\n        * an operator (represented by a single byte)\n        * a complete operand\n        * part of an operand (operands can have more than just 1 byte)\n            * example: `PUSH20` - used to push a 20-byte (160-bit) value onto the stack\n    * example\n        * `ADD` opcode is represented as `0x01`\n        * `PUSH1` opcode is represented as `60` and expects a 1-byte operand\n        * bytecode to analyse: `0x6001600201` -\u003e `60 01 60 02 01`\n        * byte `60` is the `PUSH1` opcode\n            * adds a byte to the Stack\n            * The `PUSH1` opcode is an operator that expects a 1-byte operand\n            * Then the complete statement is `60 01`\n        * `60 02` // similar\n        * final result: number 3 on the Stack\n        * digression\n            * byte 01 was used both as an operand and operator\n            * it’s easy to figure out what it represents in the context of how it was used\n    * you cannot generate the exact original Solidity source code from the EVM bytecode\n        * process of compiling involves\n            * optimizations\n            * transformations\n            * and potentially even loss of information\n                * example\n                    * during complication the function names and their input parameters are hashed to generate the function selectors\n                    * to compute function selector\n                        1. concatenate the function name and parameter types without spaces or commas: `myFunction(uint256,address)``\n                        1. calculate the keccak-256 (sha3) hash of the concatenated string\n                        1. take the first 4 bytes of the hash\n* can be described as a global decentralized state machine\n    * more than a distributed ledger\n        * analogy of a 'distributed ledger' is often used to describe blockchains like Bitcoin\n            * ledger maintains a record of activity which must adhere to a set of rules that govern what someone can and cannot do to modify the ledger\n                * example: Bitcoin address cannot spend more Bitcoin than it has previously received\n                * Ethereum has its own native cryptocurrency (Ether) that follows almost exactly the same intuitive rules\n        * it enables a much more powerful function: smart contracts\n    * state = the current state of all accounts and smart contracts on the blockchain\n        * includes things like account balances, contract storage, and contract code\n    * each transaction on a blockchain is a transition of state\n    * EVM is the engine that processes transactions and executes the corresponding smart contract code\n        * leads to state changes\n        * at any given block in the chain, Ethereum has one and only one 'canonical' state\n            * EVM is what defines the rules for computing a new valid state from block to block\n\n## gas\n* is a measure of computational work required to execute operations or transactions on the network\n    * opcodes have a base gas cost used to pay for executing the transaction\n        * example: KECCAK256\n            * cost: 30 + 6 for every 256 bits of data being hashed\n    * there isn't any actual token for gas\n        * example: you can't own 1000 gas\n        * exists only inside of the Ethereum virtual machine as a count of how much work is being performed\n* is the fee paid for executing transactions on the Ethereum blockchain\n    * example\n        * simple transaction of moving ETH between two addresses\n        * we know that this transaction requires 21,000 units\n        * base fee for standard speed at the moment of writing is 20 gwei\n        * gas fee = gas units (limit) * gas price per unit (in gwei)\n        * 21,000 * 20 = 420,000 gwei\n        * 420,000 gwei is 0.00042 ETH, which is at the current prices 0.63 USD (1 ETH = $1500)\n* gas prices change constantly and there are a number of websites where you can check the current price\n    * https://etherscan.io/gastracker\n* if Ether (ETH) was directly used as the unit of transaction cost instead of gas, it would lead to several potential problems:\n    * reduced flexibility\n        * gas allows for adjustments to the cost of computation without affecting the underlying value of Ether\n        * if Ether were used directly\n            * any change in pricing would directly impact the value of the cryptocurrency\n            * it would be difficult to prevent attackers from flooding the network with low-cost transactions\n            * cost of computation should not go up or down just because the price of ether changes\n                * it's helpful to separate out the price of computation from the price of the ether token\n    * difficulty in predictability\n        * Ether's value can be volatile, which means that transaction costs would fluctuate with the market price\n        * this could lead to unpredictable costs for users and could make it more challenging to budget for transactions\n* is used to\n    * prevent infinite loops\n    * computational resource exhaustion\n    * prioritize transactions on the network\n    * prevent Sybil attacks\n        * by discouraging the creation of a large number of malicious identities\n        * solution: prevents an attacker from overwhelming the network with a massive number of transactions\n            * as each transaction costs some amount of gas\n    * solve halting problem\n        * problem = it's generally impossible to determine whether that program will eventually halt or continue running indefinitely\n        * solution: program will eventually run out of gas and the transaction will be reverted\n* gas has a price, denominated in ether (ETH)\n    * users set the gas price they are willing to pay to have their transaction or smart contract executed\n    * miners prioritize transactions with higher gas prices because they earn the fees associated with the gas\n    * analogy\n        * gas price as the hourly wage for the miner\n        * gas cost as their timesheet of work performed\n* every operation consumes a certain amount of gas\n    * is paid by users to compensate miners for the computational work they perform\n    * total gas fee = gas used * gas price\n* each block has a gas limit\n    * maximum amount of gas that can be consumed in a block\n    * transaction sender is refunded the difference between the max fee and the sum of the base fee and tip\n* some operations can result in a gas refund\n    * example: if a smart contract deletes a storage slot, it gets a gas refund\n        * digression\n            * London Upgrade through EIP-3529: remove gas refunds for `SELFDESTRUCT`, and reduce gas refunds for `SSTORE` to a lower level\n            * practically speaking gas refunds for selfdestruct was not encouraging the freeing up of network space\n                * was encouraging the speculation on gas prices (in an extremely inefficient manner) via GAS tokens\n                * was filling the blockchain with space-consuming gastokens and transactions just to get some cheap gas back\n                * example\n                    1. during a period of lower gas prices you deploy contractA (called usually GasToken)\n                    1. during gas prices spike you'd self-destruct contractA and receive gas refund\n                    1. you can use that gas refund for paying for transaction during spike\n    * refund is only applied at the end of the transaction\n        * the full gas must be made available in order to execute the full transaction\n* it's important to estimate the gas needed for a transaction or smart contract execution\n    * if too small =\u003e the operation will be reverted and any state changes will be discarded\n        * miner still includes it in the blockchain as a \"failed transaction\", collecting the fees for it\n            * sender still pays for the gas consumed up to that point\n            * the real work for the miner was in performing the computation\n                * they will never get those resources back either\n                * it's only fair that you pay them for the work they did, even though your badly designed transaction ran out of gas\n    * if too big =\u003e the excess gas is refunded (refund = max fee - base fee + tip)\n        * max fee (maxFeePerGas)\n            * maximum limit to pay for their transaction to be executed\n            * must exceed the sum of the base fee and the tip\n        * providing too big of a fee is also different than providing too much ether\n            * if you set a very high gas price, you will end up paying lots of ether for only a few operations\n                * similar to super high transaction fee in bitcoin\n            * if you provided a normal gas price, however, and just attached more ether than was needed to pay for the gas that your transaction consumed\n                * excess amount will be refunded back to you\n                * miners only charge you for the work that they actually do\n* EIP-1559\n    * implemented in the London Hard Fork upgrade\n    * went live in August 2021\n    * introduces a new fee structure that separates transaction fees\n        * NOT designed to lower gas fees but to make them more transparent and predictable\n        * two components\n            * base fee\n                * minimum fee required to include a transaction in a block\n                * determined by network congestion\n                    * example\n                        * when the network is busy, the base fee increases\n                        * when it's less congested, the base fee decreases\n                    * increase/decrease is predictable and will be the same for all users\n                    * removing the need for each and every wallets to generate their own individual gas estimation strategies\n                * is burned\n                    * removed from circulation\n                    * reducing the overall supply of Ether\n                    * miners have less control over manipulating transaction fees\n                        * no reason into bumping base price by putting load on the network\n                    * benefits all Ether holders equally, rather than exclusively benefiting validators\n                        * creates what EIP-1559 coordinator Tim Beiko refers to as an “ETH buyback” mechanism\n                        * ETH is paid back to the protocol and the supply gets reduced\n            * priority fee\n                * optional tip to incentivize miners to include their transaction in the next block\n                * goes directly to the miner\n    * similar to a delivery service\n        * lower fee for regular delivery or a higher fee for express delivery\n        * during busy times, like the holiday season, the delivery service may increase the standard delivery fee\n            * increase will be set by the delivery company and will affect all customers equally\n    * comparable to Bitcoin’s difficulty adjustment\n    * oracles might run into issues under EIP-1559 during periods of high congestion\n        * oracles are used when you require off-chain data\n            * example: Oraclize or ChainLink\n        * they need to provide the pricing information for nearly all of DeFi\n            * example: in lending protocols, it influences interest rates and collateral ratios\n        * might end up paying incredibly high fees in order to ensure the pricing information reaches the DeFi application in a timely manner\n    * context: original Ethereum gas fee system\n        * simple auction system: unpredictable and inefficient\n            * users bid a random amount of money to pay for each transaction\n                * we can see a large divergence of transaction fees paid by different users in a single block\n                    * many users often overpay by more than 5x\n                    * example\n                        ![alt text](img/pre_eip1559_overpay.png)\n            * when the network becomes busy, this system causes gas fees to become high and unpredictable\n            * not easy to quick-fix\n                * possible improvement: users submit bids as normal, then everyone pays only the lowest bid that was included in the block\n                    * can be easily gamed by miners who will fill up their own blocks in order to increase the minimum fee\n                    * gameable by transaction senders who collude with miners\n        * similar to the way ride-sharing services calculate ride fees\n            * when demand for rides is higher, prices go up for everyone who wants a ride\n        * problem: Ethereum network becomes busy\n            * example\n                * CryptoKitty users have reached in excess of 1.5 million(25% of total Ethereal traffic in peak times)\n                * trade on a new decentralized cryptocurrency exchange\n            * result: users trying to push their transactions by paying absurdly high gas fees\n                * gas fees become unpredictable\n                * users must guess how much to pay for a transaction\n        * as Ethereum has gained new users, the network has become more congested\n            * gas fees have become more volatile\n            * many users have inadvertently overpaid for their transactions\n\n## solidity\n1. minimize on-chain data\n    * storage operations are over 100x more costly than memory operations\n        * OPcodes `mload` and `mstore` only cost `3` gas units while storage operations\n        * `sload` and `sstore` cost at least 100 units\n    * keep all data off-chain\n        * save the smart contract’s critical info on-chain\n        * save part of the system (metadata, etc .. ) on a centralized server\n    * data that does not need to be accessed on-chain can be stored in events\n1. minimize storage read/writes\n    * save intermediate results in memory and assign results to storage after all calculations\n    * caching the length in for loops\n        * reading array length at each iteration of the loop takes 6 gas\n            * 3 for mload and 3 to place memory_offset in the stack.\n        * caching the array length in the stack saves around 3 gas per iteration\n            * storage =\u003e extra sload operation\n                * 100 additional extra gas (EIP-2929) for each iteration except for the first\n            * memory =\u003e extra mload operation\n                * 3 additional gas for each iteration except for the first\n            * calldata =\u003e extra calldataload operation\n                * 3 additional gas for each iteration except for the first) These\n            * extra costs can be avoided by caching the array length (in the stack)\n                ```\n                uint _length = arr.length\n                ```\n1. use storage pointers instead of memory\n    * example\n        ```\n        mapping(uint256 =\u003e User) public users;\n        User storage _user = users[_id];\n        ```\n        is cheaper\n        ```\n        mapping(uint256 =\u003e User) public users;\n        User memory _user = users[_id]; // involves copying\n        ```\n1. use calldata instead of memory\n    * more cost-effective to load them immediately from calldata\n        * does not require copying variables to memory\n1. avoid loops\n    * it consumes a lot of gas\n    * it can prevent contract from being carried out beyond the block gas limit\n    * use mappings\n        * except when iteration is required or it is possible to pack data types (arrays are iterable and packable)\n1. minimize the number of storage slots used\n    * gas cost for storage usage is calculated based on the number of storage slots used\n    * each storage slot has a size of 256 bits\n    * you can pack multiple variables within a single storage slot\n1. use 256 byte types\n    * example: `uint256`\n    * EVM performs operations in 256-bit chunks\n        * using uint8 means the EVM has to first convert it to uint256\n        * conversion costs extra gas\n1. get gas refund for free up storage\n    * has the same effect as reassigning the value type with its default value\n    * mappings are unaffected by deletion\n        * slots of values are random (based on key hash) and generally unknown\n1. use immutable and constant\n    * evaluated at compile-time and are stored in the bytecode of the contract\n1. enable the Compiler Optimizer\n    * several optimization tools available: solc optimizer, Truffle’s build optimizer, and Remix’s Solidity compiler\n1. use short circuit rule\n    * disjunction: if the first function evaluates to true, the second function is not executed\n    * conjunction: if the first function evaluates to false, the second function is skipped entirely\n1. move the modifiers require statements into an internal virtual function\n    * modifier code is substituted by compiler to every method that uses this modifier\n    * example\n        ```\n        modifier onlyOwner() {\n            require(msg.sender == owner, \"Only owner can call this function\");\n            _;\n        }\n        ```\n        into\n        ```\n        modifier onlyOwner() {\n            _onlyOwner();\n            _;\n\n        function _onlyOwner() private {\n            require(msg.sender == owner, \"Only owner can call this function\");\n        }\n        ```\n1. use Libraries\n    * extract common functions into a single library and then deploy this library just once\n1. use layer 2 solutions\n    * works by creating a network of payment channels on top of a blockchain network\n    * enable offloading of transaction processing from the main Ethereum chain\n    * solutions\n        * rollups\n            * transactions occur off-chain on the rollup chain itself\n                * only a summary or commitment of the transactions is recorded on the Ethereum mainnet\n                    * smart contract on the Ethereum mainnet checks that the commitment is valid\n            * smart contract part can be imagined as ERC20\n                * balance of each participant is recorded in the contract\n                * hundreds \"transfer\" would be packaged into one transaction\n                    * contract can disassemble these \"transfer\" and verify\n                * two merkle trees are used for the record\n                    1. one is to record addresses, so only an index can represent an address\n                        * in rollup transaction recipient's address is replaced by an index value much smaller\n                    1. the other tree records balance and nonce\n                        * rollup transaction does not require a nonce value since it can be computed from the previous state\n            * can be further categorized into two types\n                * optimistic rollups\n                    * assume transaction validity by default unless proven otherwise\n                        * require dispute resolution mechanisms in case of fraud or incorrect transaction execution\n                    * example: Optimism\n                * zero-knowledge (zk)-rollups\n                    * use advanced cryptographic techniques to validate transactions\n                    * compress and store the user state on-chain in a Merkle tree\n                    * transfer the state transition of the user states to the off-chain\n                        * zkSNARK proof is used to ensure the correctness of the off-chain state transition\n                    * example: ZK-Sync\n        * sidechains\n            * separate blockchains that are interoperable with the Ethereum mainnet\n                * has its own consensus mechanism and can have different rules and features\n            * to move assets between the main chain and a sidechain, you typically need to use a bridge\n                * involves locking assets on the main chain and minting corresponding tokens on the sidechain\n            * example: Polygon, xDai\n        * channels\n            * parties can exchange an unlimited amount of transactions off-chain\n                * example\n                    * Alice sends a signed message to Bob saying \"I send you 1 ETH\"\n                    * Bob counter-signs the message, indicating his agreement to the new state\n            * only submitting two transactions to the mainchain\n                * open the channel\n                    * deploy a smart contract\n                    * fund smart contract with an initial deposit\n                * close the channel\n                    * submitting the final state to the smart contract on the mainnet\n                    * smart contract verifies the final state and distributes the funds accordingly\n            * example: Raiden, Celer Network, Connext\n1. use in-line assembly code\n    * efficient code that can be executed directly by the EVM without the need for expensive Solidity opcodes\n    * more precise control over memory and storage usage\n1. don't assigning default values\n    * every variable assignment in Solidity costs gas\n    * example\n        ```\n        uint256 value\n        ```\n        is cheaper than\n        ```\n        uint256 value = 0\n        ```\n1. memory is very cheap to allocate as long as it is small\n    * past a certain point (32 kilobytes) in a single transaction, the memory cost enters into a quadratic section\n    * example\n        ```\n        contract smallArraySize {\n            // Function Execution Cost = 21,903\n            function checkArray() external {\n                uint256[100] memory myArr;\n            }\n        }\n        contract LargeArraySize {\n            // Function Execution Cost = 276,750\n            function checkArray() external {\n                uint256[10000] memory myArr;\n            }\n        }\n        contract VeryLargeArraySize {\n            // Function Execution Cost = 20,154,094\n            function checkArray() external {\n                uint256[100000] memory myArr;\n            }\n        ```\n1. batching\n    * consolidate data retrieval by calling a function that returns all the required data instead of making separate calls for each data element\n1. use external function modifiers\n    * function parameters are not copied into memory but are read directly from the call data\n1. use erc1167 to deploy the same contract many time\n    * standardized, gas-efficient way to deploy a bunch of contract clones from a factory\n    * not only minimizes length, but it is also literally a “minimal” proxy that does nothing but proxying\n    * address in EIP1167 is hardcoded in bytecode and remain unchangeable\n    * example\n        * one of the most famous proxy contract users is Uniswap\n            * has a factory pattern to create exchanges for each ERC20 tokens\n            * has one exchange instance that contains full bytecode as the program logic, and the remainders are all proxies\n            * https://etherscan.io/address/0x09cabec1ead1c0ba254b09efb3ee13841712be14#code\n                * a short bytecode, which is unlikely an implementation of an exchange\n                * what it does is blindly relay every incoming transaction to the reference contract by delegatecall\n            * every proxy is a 100% replica of that contract but serving for different tokens\n            * length of the creation code of Uniswap exchange implementation is 12468 bytes\n                * proxy contract, however, has only 46 bytes\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtumilowicz%2Fethereum-gas-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtumilowicz%2Fethereum-gas-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtumilowicz%2Fethereum-gas-workshop/lists"}