【问题标题】:Reading contract balances with Waffle?使用 Waffle 读取合同余额?
【发布时间】:2021-09-08 15:01:18
【问题描述】:

上下文

采用 waffle 示例后,我在读取使用 Waffle 中的单元测试生成的合同余额时遇到了一些困难。

测试文件

import {expect, use} from 'chai';
import {Contract, utils, Wallet} from 'ethers';
import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';

import IERC20 from '../build/IERC20.json';
import AmIRichAlready from '../build/AmIRichAlready.json';
import SolveContract from '../build/SolveContract.json';
import RandomNumberConsumer from '../build/RandomNumberConsumer.json';

use(solidity);

describe('Am I Rich Already', () => {
    // Declare contracts
    let mockERC20: Contract;
    let askRootContract: Contract;
    let solveRootContract: Contract;
    let vrfContract: Contract;
    
    // Declare wallets
    let mockWallet: Wallet;
    let askRootWallet: Wallet;
    let solveRootWallet: Wallet;
    let vrfWallet: Wallet;

    beforeEach(async () => {
        
        // generate random wallets or random origin 
        //const [mockWallet, askRootWallet, solveRootWallet, vrfWallet] = Wallet.createRandom();
        //const original = Wallet.createRandom();
        
        // specify wallet balances
        const provider = new MockProvider(
            {
                ganacheOptions: {
                    // The private key is used to generate the four respective wallet addresses.
                    accounts: [
                        {balance: '16862680000000000001', secretKey: '0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c1'}, 
                        {balance: '16862680000000000002', secretKey: '0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c2'}, 
                        {balance: '16862680000000000003', secretKey: '0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c3'},
                        {balance: '16862680000000000004', secretKey: '0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c4'}
                    ]
                }
            }
        );
        
        [mockWallet, askRootWallet, solveRootWallet, vrfWallet] = provider.getWallets();
        mockERC20 = await deployMockContract(mockWallet, IERC20.abi);
        askRootContract = await deployContract(askRootWallet, AmIRichAlready, [mockERC20.address]);
        solveRootContract = await deployContract(solveRootWallet, SolveContract, [mockERC20.address]);
        vrfContract = await deployContract(vrfWallet, RandomNumberConsumer);
    });

    // custom test in AskRoot contract
    it('checks askRootContract address is returned correctly', async () => {
        expect(await askRootContract.getAddressThis()).to.be.equal('0x82A666453d8aa239eEBE4578E83cD0988D62c83F');
    });
    
    // custom test in AskRoot contract
    it('checks askRootWallet address balance is returned correctly', async () => {
        expect(await askRootContract.getAddressThisBalance()).to.be.equal(9001);
    }); 
});

合同示例

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

// Example contract of a TestContract.
contract SolveContract {
    
    bool forTestingPurposes;    // Boolean to run test on this contract
    
    TemplateTestContract testContract;  // Create variable for the testContract which needs to be solved.
    address payable owner;              // Create variable for the owner which solves the test contract.

    // Constructor to initialise the contract variables.
    constructor(address testAddress) public payable {
        testContract = TemplateTestContract(testAddress);   // Initialise the testContract variable.
        owner = msg.sender;                                 // Initialise the owner of the contract to be the creator of the contract.
    }
    
    // Function to solve the testContract.
    function solve() public payable returns(uint256){
        testContract.differentFunctionName(owner);
        return owner.balance;
    }

    // Example of the main function which solves the testContract.
    // Calculates the squre root function.
    function main(uint x) pure public returns(uint y) {
        uint z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }
    
    
    // Getter function for the Ownership.
    function getOwner() public view returns (address) { 
        return owner;
    }
    
    // Getter function for the address(this).
    function getAddressThis() public view returns (address) { 
        return address(this);
    }
    
    // Getter function for the balance of the contract.
    function getBalance() public view returns (uint) {
        //return address(this).balance;
        //testAddress.balance;
        return owner.balance;
    }
    
    // Getter function for the forTestingPurposes boolean.
    function getForTestingPurposes() public view returns (bool){   
        return forTestingPurposes;
    }
    
}

// TemplateTestContract so the SolveContract knows the structure of the testContract.
abstract contract TemplateTestContract {
    function differentFunctionName(address payable hunter) public virtual;
}

测试输出

1) checks askRootWallet address balance is returned correctly
     AssertionError: Expected "0" to be equal 9001
      at Context.it (test/AmIRichAlready.test.ts:53:76)
      at process._tickCallback (internal/process/next_tick.js:68:7)

问题

如何在 Waffle 测试中(设置)和读出特定合约的钱包地址余额?

【问题讨论】:

    标签: unit-testing solidity smartcontracts balance


    【解决方案1】:

    您的测试脚本正在调用函数getAddressThisBalance(),但该函数未在合约中定义。

    不同的 JSON-RPC 包装器在对不存在的合约函数执行调用(只读,无事务)时行为不同。有的返回undefined,有的抛出异常,Waffle 似乎返回了一个可以类型转换为0 的值。

    解决方案:

    1. 统一合约函数getBalance()和JS sn-p调用getAddressThisBalance()。例如。将 JS 调用改为getBalance()

    2. 在你的 getBalance() 合约函数中取消注释 return address(this).balance; 行。该表达式返回合约的当前余额。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-14
      • 2022-09-26
      • 2018-06-22
      • 2021-03-23
      • 2022-11-11
      • 2018-06-22
      • 2019-10-11
      • 1970-01-01
      相关资源
      最近更新 更多