-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add More Method For Enhancing Gas Efficiency Ref#454 #491
Open
Last-emo-boy
wants to merge
7
commits into
Conflux-Chain:main
Choose a base branch
from
Last-emo-boy:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
24eb415
Updating regarding the issue #430
Last-emo-boy a7c5299
Update introduction-to-smart-contracts.md
Last-emo-boy de96f8f
Merge remote-tracking branch 'upstream/main'
Last-emo-boy 3adff31
Merge branch 'main' of https://github.com/Conflux-Chain/conflux-docum…
Last-emo-boy f122dc3
Revert "Update introduction-to-smart-contracts.md"
Last-emo-boy e684384
More Methods For Enhancing Gas Efficiency
Last-emo-boy c18a997
Merge branch 'main' of https://github.com/Last-emo-boy/conflux-docume…
Last-emo-boy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
docs/general/build/smart-contracts/gas-optimization/compiler-optimization.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--- | ||
|
||
title: Optimize with Compiler Optimization | ||
displayed_sidebar: generalSidebar | ||
|
||
--- | ||
|
||
# Compiler Optimization for Gas Efficiency | ||
|
||
Minimizing gas costs is a paramount concern for smart contract developers, given the significant expenses associated with deploying and interacting with contracts on the blockchain. Beyond strategic coding practices, leveraging compiler optimization settings is a critical, yet often overlooked, avenue for gas savings. | ||
|
||
Solidity's compiler, solc, provides an optimization feature designed to reduce the bytecode size of your contracts, thereby lowering deployment and execution costs. This optimization process involves various techniques, such as removing unused code, simplifying expressions, and reordering instructions. | ||
|
||
## Optimization Runs: A Double-Edged Sword | ||
|
||
At the heart of solc's optimization feature is the concept of "optimization runs." This setting determines the number of times the compiler attempts to optimize the bytecode. A higher number of runs performs more thorough optimization, potentially leading to more significant gas savings. However, this is not without trade-offs. | ||
|
||
- **Lower Runs**: Fewer optimization runs can result in less optimized bytecode, leading to higher gas costs during contract execution. However, the compilation process is quicker, which might be beneficial during rapid development and testing phases. | ||
|
||
- **Higher Runs**: More optimization runs can significantly reduce gas costs for complex contracts by producing highly optimized bytecode. The downside is a longer compilation time and potentially increased complexity in debugging, as the optimized code may diverge more from the source code. | ||
|
||
## Demonstrating the Impact | ||
|
||
Consider a contract that performs multiple arithmetic operations and stores numerous variables: | ||
|
||
```solidity | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
contract GasOptimizationDemo { | ||
uint256 public result; | ||
|
||
function complexComputation(uint256 a, uint256 b) external { | ||
for (uint256 i = 0; i < 10; i++) { | ||
result += a * b + i; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Compiled without optimization, the `complexComputation` function may consume approximately 42,000 gas per transaction. By adjusting the optimization runs, we observe the following: | ||
|
||
- **200 Runs**: Gas consumption drops to about 39,500, a modest improvement. | ||
- **2000 Runs**: Gas consumption further reduces to approximately 37,000, showcasing more significant savings. | ||
|
||
### Recommendations for Gas Optimization: | ||
|
||
🌟 While determining the optimal number of optimization runs, consider the trade-off between compilation time and gas efficiency. For production contracts, especially those with complex logic and high interaction frequency, opting for a higher number of optimization runs can lead to substantial long-term savings. During development and testing, a lower number might suffice to speed up the iteration cycle. |
77 changes: 77 additions & 0 deletions
77
docs/general/build/smart-contracts/gas-optimization/inline-assembly.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--- | ||
|
||
title: Optimizing Gas with Inline Assembly | ||
displayed_sidebar: generalSidebar | ||
|
||
--- | ||
|
||
# Optimizing Gas with Inline Assembly | ||
|
||
Inline assembly in Solidity offers a low-level avenue to interact directly with the Ethereum Virtual Machine (EVM), allowing for more granular control over its operations. This feature can be instrumental in optimizing gas consumption, especially in complex smart contracts where every bit of efficiency counts. However, it's a tool that comes with its caveats, requiring a deep understanding of the EVM and careful consideration to avoid security pitfalls. | ||
|
||
## What is Inline Assembly? | ||
|
||
Inline assembly refers to the ability to write assembly code within Solidity contracts. Assembly language is a low-level programming language that provides direct control over the operations executed by the EVM. By using inline assembly, developers can write more optimized code that executes with fewer computational steps and, therefore, at a lower gas cost than what might be possible with high-level Solidity alone. | ||
|
||
## Advantages of Inline Assembly for Gas Optimization | ||
|
||
- **Efficiency**: Inline assembly can perform operations with fewer instructions than equivalent high-level Solidity code, leading to significant gas savings. | ||
- **Control**: Offers direct control over EVM operations, allowing developers to utilize specific instructions that are not accessible or efficiently implementable in Solidity. | ||
- **Flexibility**: Enables the implementation of complex algorithms and logic that require optimization beyond what the Solidity compiler can provide. | ||
|
||
## Use Cases | ||
|
||
Inline assembly is particularly useful for: | ||
- Implementing cryptographic functions directly in the EVM for efficiency. | ||
- Accessing specific EVM opcodes for operations like bit manipulation, which can be more gas-efficient than their Solidity counterparts. | ||
- Optimizing certain mathematical operations that are gas-intensive in high-level Solidity. | ||
|
||
Certainly! Let's delve deeper into the example and explain the intricacies of how inline assembly works within the context of the Solidity code provided. This will help clarify the optimization benefits and the specific assembly instructions used. | ||
|
||
### Detailed Breakdown of the Inline Assembly Example | ||
|
||
The example provided demonstrates a basic arithmetic operation—adding two numbers—using Solidity's inline assembly feature. Inline assembly allows direct interaction with the Ethereum Virtual Machine (EVM) through assembly language, offering potential gas savings by bypassing some of the higher-level abstractions of Solidity. | ||
|
||
```solidity | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
contract AssemblyOptimization { | ||
function add(uint256 a, uint256 b) public pure returns (uint256) { | ||
assembly { | ||
let result := add(a, b) | ||
mstore(0x0, result) | ||
return(0x0, 32) | ||
} | ||
} | ||
} | ||
``` | ||
|
||
#### Assembly Instructions Breakdown | ||
|
||
- `let result := add(a, b)`: This line declares a new variable `result` within the assembly block and assigns it the value of `a + b`. The `add` instruction is an EVM opcode that efficiently performs addition. Unlike Solidity's addition, which includes safety checks for overflow, the `add` opcode directly computes the sum, assuming that inputs are valid, thus saving gas. | ||
|
||
- `mstore(0x0, result)`: The `mstore` instruction stores the `result` in memory. The first parameter (`0x0`) specifies the start position in memory where the `result` should be stored. In this case, it's the position `0x0`, the beginning of the available memory space. This operation is direct and efficient, closely controlling how and where data is stored in memory. | ||
|
||
- `return(0x0, 32)`: This instruction returns the value stored in memory to the caller. The first parameter (`0x0`) indicates the start position of the data to return, and `32` specifies the size of the data in bytes (since a `uint256` is 32 bytes). This bypasses the automatic return mechanisms of Solidity, giving you precise control over what is returned and how it's formatted, potentially saving gas by minimizing unnecessary data handling. | ||
|
||
#### Gas Savings Potential | ||
|
||
- **Direct opcode usage**: By directly using EVM opcodes (`add`, `mstore`, `return`), the assembly block avoids the overhead associated with Solidity's safety checks and higher-level abstractions. For example, Solidity's addition operation checks for overflows, which consumes more gas. | ||
|
||
- **Memory management**: The example demonstrates low-level memory management (`mstore`, `return`), offering more control over how data is handled and potentially reducing gas costs compared to Solidity's automatic memory management. | ||
|
||
#### Considerations | ||
|
||
While this example is relatively straightforward, it showcases the potential for gas savings with inline assembly. However, it's essential to approach inline assembly with caution: | ||
|
||
- **Security**: The lack of safety checks in assembly (e.g., for overflows) means that developers need to ensure their code is secure against such vulnerabilities. | ||
- **Maintainability**: Assembly code can be harder to read and maintain, making it potentially more error-prone and difficult for other developers to understand. | ||
|
||
In this example, the addition is performed using an assembly block, which directly uses the `add` opcode of the EVM. This is more direct and may use less gas than performing the addition in Solidity, especially in more complex operations where the optimization potential is higher. | ||
|
||
### Recommendations for Gas Optimization: | ||
|
||
🌟 While inline assembly can provide substantial gas savings, it should be used sparingly and only by those with a thorough understanding of the EVM and Solidity. Incorrect use of inline assembly can lead to serious security vulnerabilities, including susceptibility to reentrancy attacks, issues with gas estimation, and other unforeseen side effects. | ||
|
||
**Always test assembly code thoroughly** and consider the maintenance and security implications of integrating low-level operations into your contracts. |
62 changes: 62 additions & 0 deletions
62
docs/general/build/smart-contracts/gas-optimization/staticcall.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
|
||
title: Optimizing with `staticcall` for Gas Efficiency | ||
displayed_sidebar: generalSidebar | ||
|
||
--- | ||
|
||
# Optimizing with `staticcall` for Gas Efficiency | ||
|
||
One of the subtler, yet powerful, optimization techniques in Solidity involves the judicious use of `staticcall`, particularly when interacting with external contracts. `staticcall` is a type of Ethereum Virtual Machine (EVM) call that is used for executing external contract functions that do not alter the state. This kind of call ensures that no state modification occurs, making it a safer and, in some scenarioes, a more gas-efficient alternative to regular calls. | ||
|
||
## Understanding `staticcall` | ||
|
||
In Ethereum, every call to an external contract function can potentially modify the state of the blockchain, which requires a certain amount of gas. However, operations that purely read data without altering the state consume less gas. `staticcall` is specifically designed for these scenarios. By using `staticcall`, you explicitly signal to the EVM and to other developers that the called function does not write to the blockchain. This can save gas in certain situations and also adds a layer of security to your contract by preventing state changes during the call. | ||
|
||
## How It Works | ||
|
||
Solidity abstracts `staticcall` through its language syntax, primarily through the `view` and `pure` function modifiers. When you call a function marked as `view` or `pure` on an external contract interface, Solidity automatically uses `staticcall`. However, you can also manually invoke `staticcall` through low-level calls for more complex scenarios or when interacting with contracts without a Solidity interface. | ||
|
||
## Benefits of `staticcall` | ||
|
||
- **Gas Efficiency**: For functions that only need to read data from the blockchain, `staticcall` is more gas-efficient than a regular call. | ||
- **Security**: By preventing state changes, `staticcall` ensures that the called function cannot alter the contract's state or the state of other contracts. This makes contracts more predictable and secure. | ||
|
||
You're right; the example provided for demonstrating the benefits of `staticcall` might not fully showcase its advantages, especially since `staticcall` is implicitly used in Solidity for `view` and `pure` functions. To better illustrate the benefits, let's delve into a scenario where the explicit use of `staticcall` can optimize gas consumption, particularly when interacting with contracts in a more granular manner. | ||
|
||
### Example | ||
|
||
Consider a case where you have a contract that interacts with various external contracts, and you need to ensure that these interactions do not alter the state, aiming to optimize for gas. In such scenarios, explicitly using `staticcall` can help, especially when you're working with contracts that don't have Solidity interfaces or when you need to ensure that a fallback function does not alter the state. | ||
|
||
```solidity | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
contract ExternalPriceFeed { | ||
function getPrice() external pure returns (uint256) { | ||
return 100; // Simplified example | ||
} | ||
} | ||
|
||
contract PriceChecker { | ||
/* | ||
Explicitly uses low-level calls to interact with another contract. | ||
This method ensures that the call is a 'static' call, meaning it cannot alter the state. | ||
Useful for interacting with contracts where you want to guarantee no state changes. | ||
*/ | ||
|
||
function checkPrice(address priceFeedAddress) external returns (uint256) { | ||
(bool success, bytes memory data) = priceFeedAddress.staticcall( | ||
abi.encodeWithSignature("getPrice()") | ||
); | ||
require(success, "Static call failed"); | ||
return abi.decode(data, (uint256)); | ||
} | ||
} | ||
``` | ||
|
||
In this refined example, `PriceChecker` uses a low-level `staticcall` to interact with `ExternalPriceFeed`. The key here is the explicit control over the type of call made to the external contract, ensuring it's a read-only operation. This approach can prevent unintended state changes, which is particularly important in complex systems where contracts interact with various external components. It provides an extra layer of security and optimizes gas usage by ensuring that only necessary state changes are paid for. | ||
|
||
### Recommendations for Gas Optimization: | ||
|
||
🌟 Utilize `staticcall` (implicitly or explicitly) when interacting with external contracts for read-only operations. This not only optimizes gas consumption but also adds an extra layer of security by ensuring that these calls cannot perform state modifications. Always assess the function being called to confirm that a `staticcall` is appropriate for the intended interaction. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks rather strange, like the answer chatgpt gave you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, many of the words generated by chatgpt are nonsense and repetitive. I think it is not suitable to be placed directly in the document.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I generate some of the code snippet with Cody, failed to review that, I will fix that🤔