Source-linked AI summary
Under-Optimized Smart Contracts Devour Your Money
Ting Chen, Xiaoqi Li, Xiapu Luo, Xiaosong Zhang
TL;DR
Under-optimized smart contracts consume more gas than necessary, overcharging creators or users, while Solidity fails to optimize identified gas-costly patterns. The paper investigates these patterns and develops GASPER, a symbolic-execution tool for locating them in bytecode. Applied to deployed contracts, GASPER finds that 93.5%, 90.1% and 80% suffer from three representative patterns, respectively.
Problem
Under-optimized smart contracts consume more gas than necessary, and developers lack guidelines and practical means to identify and replace gas-costly bytecode.
Method
The paper investigates Solidity's optimization of 7 gas-costly patterns in 2 categories and develops GASPER to discover 3 representative patterns through symbolic execution of bytecode.
Results
93.5%, 90.1% and 80% of deployed smart contracts suffered from the three representative gas-costly patterns, respectively.
Takeaways & Limitations
Gas-efficient replacements for costly bytecodes can save money, and the prevalence of detected patterns indicates that deployed contracts are often not properly optimized for gas reduction.
Abstract
from arXiv · showhide
Smart contracts are full-fledged programs that run on blockchains (e.g., Ethereum, one of the most popular blockchains). In Ethereum, gas (in Ether, a cryptographic currency like Bitcoin) is the execution fee compensating the computing resources of miners for running smart contracts. However, we find that under-optimized smart contracts cost more gas than necessary, and therefore the creators or users will be overcharged. In this work, we conduct the first investigation on Solidity, the recommended compiler, and reveal that it fails to optimize gas-costly programming patterns. In particular, we identify 7 gas-costly patterns and group them to 2 categories. Then, we propose and develop GASPER, a new tool for automatically locating gas-costly patterns by analyzing smart contracts' bytecodes. The preliminary results on discovering 3 representative patterns from 4,240 real smart contracts show that 93.5%, 90.1% and 80% contracts suffer from these 3 patterns, respectively.
I. INTRODUCTION
Smart contracts are blockchain programs whose execution and deployment consume gas, creating monetary incentives for gas-efficient bytecode. The paper finds Solidity misses gas-costly patterns and introduces GASPER, which detects representative patterns prevalent among deployed contracts.
- Blockchain and smart contracts: Smart contracts are full-fledged blockchain programs compiled into bytecode executable by the Ethereum Virtual Machine.Ethereum smart contracts can be developed in Solidity, Serpent, or LLL, but their source is compiled into EVM bytecode.
- Blockchain and smart contracts: Gas charges compensate miners for computing resources, so under-optimized contracts can overcharge their creators or users.Transaction cost equals gas consumed multiplied by the gas price.
- Research gap: Developers lack a guideline for replacing gas-costly bytecode, while identifying inefficient patterns requires detailed knowledge of EVM execution and gas consumption.The paper therefore motivates compiler support for minimizing gas consumption.
- Contributions: Solidity fails to optimize 7 gas-costly programming patterns grouped into useless-code-related and loop-related categories.The paper presents these patterns as bytecode inefficiencies that can be replaced with gas-efficient alternatives.
- Contributions: GASPER uses symbolic execution to automatically discover 3 representative gas-costly patterns in smart-contract bytecode.The current version covers both identified categories and is being extended to support more patterns.
- Results: 93.5%, 90.1% and 80% of deployed smart contracts suffered from the three detected patterns, respectively.GASPER was applied to all deployed smart contracts through Nov. 5th, 2016.
II. BACKGROUND
Ethereum gas costs vary substantially across operations and are charged for deployment and execution. Because public methods can be called repeatedly, optimizing expensive operations can produce substantial savings.
- Gas economics: Gas is money-equivalent because users pay miners for computing resources consumed by contract deployment and execution.Gas prices and Ether exchange rates are market-determined and change over time.
- Gas economics: Repeated calls to public smart-contract methods create a scale effect that makes optimized contracts cheaper than unoptimized counterparts.The paper notes that contracts may be called unlimited times by various clients and contracts.
- Operation costs: Stack, arithmetic, bitwise, comparison, and memory operations are relatively cheap in the EVM.The EVM favors stack-related operations, and memory is freshly cleared for each message call.
- Operation costs: SLOAD and SSTORE access persistent storage and are expensive; SSTORE costs 20,000 gas for zero-to-nonzero writes and 5,000 otherwise.A 15,000-gas refund for clearing storage is committed only after successful transaction completion.
- Operation costs: Blockchain-specific operations such as BALANCE, CREATE, and CALL are very expensive, while JUMPI costs more than JUMP.Gas consumption can change as Ethereum evolves.
III. GAS-COSTLY PROGRAMMING PATTERNS
The paper identifies 7 gas-costly programming patterns and groups them into useless-code and loop-related categories. Testing Solidity 0.4.4 with optimization enabled found that none of these patterns was optimized.
- Pattern categories: 7 gas-costly patterns are classified as useless-code related or loop related.Useless-code patterns increase deployment and runtime costs, whereas loop-related patterns use expensive operations in loops.
- Compiler validation: Solidity 0.4.4 with optimization enabled failed to convert any tested gas-costly pattern into a gas-efficient bytecode pattern.The authors supplied gas-costly source patterns to Solidity and inspected the generated bytecode.
A. Category 1: Useless Code Related Patterns
The paper identifies useless-code and loop-related gas-costly patterns, showing how eliminating redundant code or computations can reduce smart-contract costs.
- Dead code: Dead code remains in Solidity bytecode even when a predicate makes a line unreachable, wasting gas.In the example, “x*x<20” is always false, so Line 4 is never executed.
- Opaque predicate: Opaque predicates have outcomes known without execution and should be removed when always true or false.The example predicate “x>1” is always true and therefore adds unnecessary gas cost.
- Loop-related patterns: Moving storage updates out of loops can reduce storage operations from 2x to 2, using one SLOAD and one SSTORE.The optimization keeps an accumulating value on the stack during iteration and writes it back after the loop.
- Loop-related patterns: A loop with a compile-time constant outcome can be replaced by its result, such as returning 5050 directly.This removes execution of the loop body when the compiler can infer the final value.
- Loop-related patterns: Loop fusion combines compatible loops, while repeated computations should be performed once and reused across iterations.Both optimizations reduce repeated operations; repeated storage-word additions are especially costly because they require SLOAD operations.
- Loop-related patterns: Comparisons with the same outcome in every loop iteration should be moved before the loop, and loop-related costs rise with iteration count.These optimizations reduce computation for users, while reducing bytecode size can lower creator costs.
IV. GASPER
GASPER automatically discovers gas-costly programming patterns directly from smart-contract bytecode, supporting detection without requiring source code.
- Tool scope: GASPER analyzes bytecode directly because only a few deployed smart contracts make their source code available.Its current version detects all category-1 patterns and one representative category-2 pattern, expensive operations in a loop.
- Symbolic execution: GASPER uses symbolic execution to traverse reachable control-flow blocks and determine feasible branches with the Z3 solver.The control-flow graph is improved during execution when new control-flow transfers are found.
A. Detection of Dead Code
GASPER detects dead code by comparing blocks executed during symbolic execution with all blocks identified in the control-flow graph.
- Detection procedure: GASPER reports blocks present in the control-flow graph but absent from symbolic execution as dead code.The procedure logs executed-block addresses, scans the CFG for all block addresses, and compares the two sets.
B. Detection of Opaque Predicates
GASPER detects opaque predicates from symbolic branch behavior and identifies expensive operations in loops through control-flow analysis.
- Opaque predicates: A conditional jump with one branch never executed during symbolic execution is classified as an opaque predicate.GASPER records whether the true or false branch executes when encountering each conditional jump.
- Expensive operations: For expensive operations in loops, GASPER finds CFG back edges, identifies loop boundaries, and searches loop bodies for supported costly operations.The current detector supports SLOAD, SSTORE, and BALANCE, with additional operations planned.
V. EVALUATION
GASPER was evaluated on Ethereum contracts and found widespread gas-costly patterns, including dead code, opaque predicates, and expensive operations inside loops.
- Evaluation setup: 27,290 contracts’ bytecodes were downloaded after scanning 566,907 addresses, of which 539,617 contained no bytecodes.Many downloaded contracts were identical in bytecode.
- Pattern prevalence: More than 70% of contracts contain all three gas-costly patterns, while more than 90% contain dead code or opaque predicates.The three patterns are dead code, opaque predicates, and expensive operations in a loop.
- Useless-code patterns: 51.7% of contracts contain more than 20 dead code blocks, and 52.6% contain more than 10 opaque predicates.The distributions of dead code blocks and opaque predicates show similar trends.
- Loop-related patterns: 69.9%, 78.5% and 21% of contracts contain SLOAD, SSTORE and BALANCE operations in a loop, respectively.Among contracts with BALANCE in a loop, 18.6% contain both SLOAD and SSTORE operations.
- Loop-related patterns: 57.1% of contracts have more than 7 SSTORE operations in a loop, while 51.5% have more than 20 SLOAD operations in a loop.Contracts without these expensive loop operations were not counted.
- Contract size: Larger contracts are likely to contain more gas-costly patterns; ARK contains 304 SLOAD and 168 SSTORE operations in loops.ARK is 34,767 bytes and was deployed at the address given in the evaluation passage.
A. Real Case 1: FirstContract
In FirstContract, GASPER identifies dead code and an opaque predicate caused by an exponentiation comparison that can never evaluate to true.
- FirstContract: GASPER discovers dead code at Line 200 and an opaque predicate at Line 199 in FirstContract.The example is the open-source contract deployed at the address specified in the passage.
- FirstContract: The predicate comparing the length of h with 2 **128 −1 is never true, so the code at Line 200 cannot execute.The function indexof converts haystack into a byte set h before performing the comparison.
B. Real Case 2: Ballot
In Ballot, GASPER finds an SLOAD inside a loop that can be moved outside the loop by caching proposals.length in a stack variable.
- Ballot: GASPER finds an SLOAD operation in a Ballot loop that can be moved outside the loop.The finding is illustrated in Fig. 11.
- Ballot: Because proposals is stored in storage, accessing proposals.length performs SLOAD on every loop iteration.The number of SLOAD operations equals proposals.length when the length is accessed during each iteration.
- Ballot: Assigning proposals.length to a stack variable allows the loop comparison to use the cached value instead.This is the gas-efficient replacement described for the costly code.
VI. RELATED WORK
Prior blockchain and smart-contract studies addressed security, verification, privacy, crime, external data, and attacks, but not gas consumption from this perspective.
- Related work: Earlier studies did not investigate smart-contract gas consumption from the perspective used in this work.The related work includes OYENTE, formal verification, HAWK, criminal-contract analysis, TOWN CRIER, and attack surveys.
- This work: This paper presents the first investigation of gas-costly bytecodes generated by Solidity and introduces GASPER for discovering representative patterns.The tool uses symbolic execution and covers three patterns in two categories.