如何在Solidity中调用contract.transfer方法时调试运行时错误?

How can I debug the runtime error when call contract.transfer method in Solidity?

我已经从 Ganache 启动了一个私有网络,并使用 truffle 将我的合约部署到网络中。部署工作正常,我可以从合同中调用一些方法。但是当我尝试将以太币转移到另一个账户时出现错误。

我的合约代码是:

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.4;
pragma experimental ABIEncoderV2;

contract Ledger {

    mapping(address => uint256) balances;

    address payable owner;

    event Transfered(address _from, address _to, uint256 amount);

    constructor() {
        owner = payable(msg.sender);
        balances[tx.origin] = 10000;
    }

    function sendCoin(address payable receiver, uint256 amount)
        payable public
        returns (bool sufficient)
    {
        require(msg.sender == owner);
        if (balances[msg.sender] < amount) return false;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        receiver.transfer(amount);
        emit Transfered(msg.sender, receiver, amount);
        return true;
    }

    function getBalance(address addr) public view returns (uint256) {
        return balances[addr];
    }

    function getBalanceInCoin(address addr)
        public
        view
        returns (uint256)
    {
        return convert(getBalance(addr), 100);
    }

    function convert(uint256 amount, uint256 conversionRate)
        public
        pure
        returns (uint256 convertedAmount)
    {
        return amount * conversionRate;
    }
}

当我 运行 它在 truffle 控制台中时:

truffle(development)> let ledger = await Ledger.deployed()
truffle(development)> let accounts = await web3.eth.getAccounts()
truffle(development)> (await ledger.sendCoin(accounts[1], 50))
Uncaught Error: Returned error: VM Exception while processing transaction: revert
    at evalmachine.<anonymous>:1:17
    at evalmachine.<anonymous>:2:49
    at sigintHandlersWrap (vm.js:273:12)
    at Script.runInContext (vm.js:142:14)
    at runScript (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:364:1)
    at Console.interpret (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:379:1)
    at bound (domain.js:421:15)
    at REPLServer.runBound [as eval] (domain.js:432:12)
    at REPLServer.onLine (repl.js:909:10)
    at REPLServer.emit (events.js:400:28)
    at REPLServer.emit (domain.js:475:12)
    at REPLServer.Interface._onLine (readline.js:434:10)
    at REPLServer.Interface._line (readline.js:791:8)
    at REPLServer.Interface._ttyWrite (readline.js:1136:14) {
  data: {
    '0xebf4283ab2e7ced42b27b67e8a25c73c7c29e26aa3c86a14c5d6bbaba2c5fc55': { error: 'revert', program_counter: 738, return: '0x' },
    stack: 'RuntimeError: VM Exception while processing transaction: revert\n' +
      '    at Function.RuntimeError.fromResults (/Applications/Ganache.app/Contents/Resources/static/node/node_modules/ganache-core/lib/utils/runtimeerror.js:94:13)\n' +
      '    at BlockchainDouble.processBlock (/Applications/Ganache.app/Contents/Resources/static/node/node_modules/ganache-core/lib/blockchain_double.js:627:24)\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:93:5)',
    name: 'RuntimeError'
  },
  hijackedStack: 'Error: Returned error: VM Exception while processing transaction: revert\n' +
    '    at Object.ErrorResponse (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/web3-core-helpers/lib/errors.js:28:1)\n' +
    '    at /Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-core-requestmanager/lib/index.js:302:1\n' +
    '    at /Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> (/Users/joey/.nvm/versions/node/v14.18.0/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:412:35)\n' +
    '    at IncomingMessage.emit (domain.js:537:15)\n' +
    '    at endReadableNT (internal/streams/readable.js:1334:12)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:82:21)'

如您所见,上述错误来自 sendCoin 方法中的 transfer 方法。我怎么知道错误来自什么以及我应该如何修复它?

用 truffle 调试是一件很痛苦的事。特别是如果你以前没有 cli 调试的经验虽然这里是他们的完整 guide。 这包括所有设置断点、显示变量、执行和打印表达式等

根据经验,如果您正在从事涉及编写单个或两个智能合约的项目,您可能想使用 remix IDE。它非常人性化,应有尽有。您可以轻松地对智能合约进行代码部署测试调试。