solidity文档中提到,如果幂运算的指数较小时,使用连乘会更节约gas,那这个临界值在哪呢,幂运算的指数到多少之后会比连乘节约gas呢?能节约多少呢,毕竟蚊子腿也是肉
solidity 文档中提到,如果幂运算的指数较小时,使用连乘会更节约 gas ,那这个临界值在哪呢,幂运算的指数到多少之后会比连乘节约 gas 呢?能节约多少呢,毕竟蚊子腿也是肉
在“checked” 模式下,幂运算仅会为小基数使用相对便宜的
exp操作码。 例如x**3的例子,表达式x*x*x也许更便宜。 在任何情况下,都建议进行 gas 消耗测试和使用优化器。
Gas 消耗计算方法参考:计算Solidity 函数的Gas 消耗。使用 Hardhat 进行测试。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Strings.sol";
interface IGasCostTest{
    function setX() external;
    function setY() external;
}
contract GasCostTest{
    uint256 public x = 2;
    uint256 public y = 2;
    function setX() external {
        x = x ** 9;
    }
    function setY() external {
        y = y * y * y * y * y * y * y * y * y;
    }
}
contract CalculateGasCost {
    string public report;
    IGasCostTest public TestAddress;
    constructor(address testAddress_){
        TestAddress = IGasCostTest(testAddress_);
    }
    function GasCost(
        string memory name,
        function() external fun
    ) public {
        uint256 u0 = gasleft();
        fun();
        uint256 u1 = gasleft();
        uint256 diff = u0 - u1;
        string memory s = report;
        report = string(abi.encodePacked(s, string(abi.encodePacked(name, " GasCost: ", Strings.toString(diff))), "\n"));
    }
    function GenReport() public {
        GasCost("setX ", TestAddress.setX);
        GasCost("setY ", TestAddress.setY);
    }
}const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Test x ^ 9", function () {
    let ContractAddress, CalculateGasCostAddress;
    before('布署合约', async function () {
        const ContractInstance = await ethers.getContractFactory("GasCostTest");
        const CalculateGasCostInstance = await ethers.getContractFactory("CalculateGasCost");
        ContractAddress = await ContractInstance.deploy();
        CalculateGasCostAddress = await CalculateGasCostInstance.deploy(ContractAddress.address);
    });
    it("CalculateGasCost", async function () {
        await CalculateGasCostAddress.GenReport();
        await CalculateGasCostAddress.GenReport();
        const res = await CalculateGasCostAddress.report();
        console.log(res);
        const x = await ContractAddress.x();
        const y = await ContractAddress.y();
        expect(x).to.equal(y);
    });
});Test x ^ 3
setX  GasCost: 8446
setY  GasCost: 6202
setX  GasCost: 8492
setY  GasCost: 6202
Test x ^ 9
setX  GasCost: 8446
setY  GasCost: 8314
setX  GasCost: 9073
setY  GasCost: 8314
Test x ^ 10
setX  GasCost: 8446
setY  GasCost: 8666
setX  GasCost: 9073
setY  GasCost: 8666Test x ^ 3
setX GasCost: 8242 
setY GasCost: 5674 
setX GasCost: 8345 
setY GasCost: 5674
# 因为会导致 uint256 溢出,所以只执行一次
Test x ^ 30
setX GasCost: 8242 
setY GasCost: 8239
Test x ^ 31
setX GasCost: 8242 
setY GasCost: 8334# 未使用 remix 优化器:
Test 1 << 3
setX  GasCost: 8468
setZ  GasCost: 5520
Test 1 << 250
setX  GasCost: 8468
setZ  GasCost: 5529
# 使用 remix 优化器:
Test 1 << 3
setX GasCost: 8264 
setZ GasCost: 5500
Test 1 << 250
setX GasCost: 8264 
setZ GasCost: 5506 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!