简体   繁体   English

测试智能合约(solidity/truffle)

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

I have these lines of code我有这些代码行

// 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];
    }
}

and I want to test the contract on how it's going to work if 6000+ different registries happen how much is going to cost.我想测试一下合同,如果发生 6000 多个不同的注册管理机构,它将如何运作将花费多少。 Thanks in advance.提前致谢。

This is the test file for now:这是现在的测试文件:

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')
    })
})

There is an explanation of manually calculating gas cost at Stack Exchange : Stack Exchange上有关于手动计算 gas 成本的解释:

I'm using the Yellow Paper, Appendix G, page 25 as reference.我正在使用黄皮书,附录 G,第 25 页作为参考。

The cost of gas to deploy your contract can be calculated like this:部署合约的 gas 成本可以这样计算:

21000 because all transactions pay this (Gtransaction) 32000 because is a contract creation (Gcreate) Your transaction will have input data, which will cost you in gas: 21000 因为所有交易都支付这个 (Gtransaction) 32000 因为是合约创建 (Gcreate) 你的交易将有输入数据,这将花费你的 gas:

4 for each byte with value zero in your input data (Gtxdatazero) 68 for each non zero byte in your input data (Gtxdatanonzero) Initialising variables and running the constructor, costs you:输入数据中每个值为零的字节 4 (Gtxdatazero) 输入数据中每个非零字节 68 (Gtxdatanonzero) 初始化变量和运行构造函数,花费你:

20000 for each SSTORE when the storage value is set to non-zero(Gsset) 5000 for each SSTORE when the storage value is set to zero (Gsreset) additional gas for each OPCODE your constructor is executing (see reference) Finally, you have to pay to store your code, and that will cost you:当存储值设置为非零时每个 SSTORE 20000(Gsset) 当存储值设置为零时每个 SSTORE 5000 (Gsreset) 构造函数正在执行的每个 OPCODE 的额外气体(参见参考资料)最后,你必须付费存储您的代码,这将花费您:

200 for each byte of code you store on the state. When you compile your code, you get your bytecode, and that's where > you can find all the OPCODES your smart contract executes.您存储在 state 上的每个代码字节为 200。当您编译代码时,您将获得字节码,这就是您可以找到智能合约执行的所有 OPCODES 的地方。

You will also get your running (or deployed) bytecode, which is the > code that will be stored on the state. It's equal to the bytecode minus the initialisation and constructor code (that are not stored in the state).您还将获得正在运行(或已部署)的字节码,这是将存储在 state 上的 > 代码。它等于字节码减去初始化和构造函数代码(未存储在状态中)。

How to know the code size using a truffle javascript test file You can use the following code in a js file inside the test folder:如何使用 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); }); }); });

Afterwards, run truffle test.之后,运行松露测试。

This article on Medium may also help if you want to automate the process:如果您想自动化该过程, 这篇关于 Medium的文章也可能有所帮助:

Measuring Gas Cost In order to determine how much gas (many cycles) of the EVM (Ethereum virtual machine) each option takes, we need to measure them.测量 Gas 成本 为了确定每个选项需要多少 EVM(以太坊虚拟机)的 gas(多少个周期),我们需要测量它们。 There are many useful blockchain features such as a system function called gasleft() that reports how much gas is left for the running contract, and it is also possible to pass functions to other functions.有许多有用的区块链功能,例如名为 gasleft() 的系统 function,它报告正在运行的合约还剩下多少气体,并且还可以将函数传递给其他函数。 We can use these features to provide a function that will measure the gas cost of a given function, fun:我们可以使用这些功能来提供一个 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, ")"); }

I will show how to calculate the cost of calling a function and then you have to do for loop for 6000 registiries.我将展示如何计算调用 function 的成本,然后您必须为 6000 个注册表执行循环。 Assuming that you initialize the contract correct:假设您正确初始化合约:

const result = await instance.setRoute()

if you console.log(result you get this object如果你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: []
}

To get the gas cost write a function:要获得 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 is a helper function: toBN是一个帮手 function:

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

finally get the gas cost:最终得到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