繁体   English   中英

测试智能合约(solidity/truffle)

[英]Test for smart contract (solidity/truffle)

我有这些代码行

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

contract wasteManagement2 {
    struct Route{
        string date; //struct date{ uint day; uint month; uint year;}
        // eg. monday
        string vehicle;
        string driver; //struct driver { string name, string lname, uint id}
        string location;
        string routebinId;
    }

    mapping (uint => Route) public routes;
    uint public routeCount;

    constructor()  {
        routeCount = 0;
    }

    function setRoute(string memory _date,string memory _vehicle, string memory _driver, string memory _location, string memory _routebinId) public{
        routes[routeCount] = Route (_date,_vehicle, _driver, _location, _routebinId);
        routeCount++;
    }

    function getRoute(uint _routeCount) public view returns(Route memory){
        return routes[_routeCount];
    }
}

我想测试一下合同,如果发生 6000 多个不同的注册管理机构,它将如何运作将花费多少。 提前致谢。

这是现在的测试文件:

const Routes = artifacts.require("Routes");

contract ("Routes", (accounts) => {
    before(async () =>  {
        instance = await Routes.deployed()
    })

    it ('ensures that the array is empty', async () => {
        let count =  await instance.setRoute()
        assert.equal(count, 0, 'The array should be empty')
    })
})

Stack Exchange上有关于手动计算 gas 成本的解释:

我正在使用黄皮书,附录 G,第 25 页作为参考。

部署合约的 gas 成本可以这样计算:

21000 因为所有交易都支付这个 (Gtransaction) 32000 因为是合约创建 (Gcreate) 你的交易将有输入数据,这将花费你的 gas:

输入数据中每个值为零的字节 4 (Gtxdatazero) 输入数据中每个非零字节 68 (Gtxdatanonzero) 初始化变量和运行构造函数,花费你:

当存储值设置为非零时每个 SSTORE 20000(Gsset) 当存储值设置为零时每个 SSTORE 5000 (Gsreset) 构造函数正在执行的每个 OPCODE 的额外气体(参见参考资料)最后,你必须付费存储您的代码,这将花费您:

您存储在 state 上的每个代码字节为 200。当您编译代码时,您将获得字节码,这就是您可以找到智能合约执行的所有 OPCODES 的地方。

您还将获得正在运行(或已部署)的字节码,这是将存储在 state 上的 > 代码。它等于字节码减去初始化和构造函数代码(未存储在状态中)。

如何使用 truffle javascript 测试文件知道代码大小您可以在测试文件夹内的 js 文件中使用以下代码:

 var YourContract = artifacts.require("YourContract"); contract('YourContract', function(accounts) { it("get the size of the contract", function() { return YourContract.deployed().then(function(instance) { var bytecode = instance.constructor._json.bytecode; var deployed = instance.constructor._json.deployedBytecode; var sizeOfB = bytecode.length / 2; var sizeOfD = deployed.length / 2; console.log("size of bytecode in bytes = ", sizeOfB); console.log("size of deployed in bytes = ", sizeOfD); console.log("initialisation and constructor code in bytes = ", sizeOfB - sizeOfD); }); }); });

之后,运行松露测试。

如果您想自动化该过程, 这篇关于 Medium的文章也可能有所帮助:

测量 Gas 成本 为了确定每个选项需要多少 EVM(以太坊虚拟机)的 gas(多少个周期),我们需要测量它们。 有许多有用的区块链功能,例如名为 gasleft() 的系统 function,它报告正在运行的合约还剩下多少气体,并且还可以将函数传递给其他函数。 我们可以使用这些功能来提供一个 function,它将测量给定 function 的 gas 成本,有趣:

 function GasCost(string memory name, function () internal returns (string memory) fun) internal returns (string memory) { uint u0 = gasleft(); string memory sm = fun(); uint u1 = gasleft(); uint diff = u0 - u1; return concat(name, " GasCost: ", stringOfUint(diff), " returns(", sm, ")"); }

我将展示如何计算调用 function 的成本,然后您必须为 6000 个注册表执行循环。 假设您正确初始化合约:

const result = await instance.setRoute()

如果你console.log(result你得到这个 object

result {
  tx: '0x1550f6f4f3e7abe0e2d39a43127714e4422e548e6a45d54a3fe12c2ed8b1c180',
  receipt: {
    transactionHash: '0x1550f6f4f3e7abe0e2d39a43127714e4422e548e6a45d54a3fe12c2ed8b1c180',
    transactionIndex: 0,
    blockHash: '0x6d13903f40a7b3c989b79accf70d5bb1f7ef673ee59a0eb534b09d375db1bd7e',
    blockNumber: 1249,
    from: '0xd76536f6b5722f78d444ba0c3b8aae84b7a226ba',
    to: '0xde7b6dd9d647e4249f85ac15e5f7c88e7e424fa',
    gasUsed: 31167,
    cumulativeGasUsed: 31167,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}

要获得 gas 成本,请写一个 function:

const getGas = async (result) => {
  const tx = await web3.eth.getTransaction(result.tx);
  const gasUsed = toBN(result.receipt.gasUsed);
  const gasPrice = toBN(tx.gasPrice);
  const gas = gasUsed.mul(gasPrice);
  return gas;
};

toBN是一个帮手 function:

const toBN = (value) => web3.utils.toBN(value);

最终得到gas成本:

const result = await instance.setRoute()
const gas = await getGas(result);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM