错误:返回的错误:处理事务时的VM异常:还原

时间:2020-10-19 14:34:58

标签: solidity truffle open-zeppelin

我有一个合同 GetNewToken ,该合同收到 OldToken ,并通过 buyTokens NewToken >

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import './NewToken.sol';
import './OldToken.sol';
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract GetNewToken {

    string  public name = "Get New Token Contract";
    address public owner;
    NewToken public newToken;
    OldToken public oldToken;

    event Bought(address buyer, uint256 amount);
    event TransferFromFailed(uint256 amount);
    
    constructor(NewToken _newToken, OldToken _oldToken) public {
        newToken = _newToken;
        oldToken = _oldToken;
        owner = msg.sender;
    }

    function buyTokens(uint256 _amount) public {
        require(_amount > 0, "amount can not be 0");
        uint256 userBalance = oldToken.balanceOf(msg.sender);

        require(userBalance >= _amount, "Not enough Old Token in your account");
        bool success = oldToken.transferFrom(msg.sender, address(this), _amount);

        if(success) {
            uint256 newBalance = newToken.balanceOf(address(this));
            require(_amount <= newBalance, "Not enough New Tokens in the contract");
            newToken.transfer(msg.sender, _amount);
            emit Bought(msg.sender, _amount);
        } else {
            emit TransferFromFailed(_amount);
            revert("oldToken.transferFrom function failed");
        }

    }
}

OldTokens NewTokens 是标准的ERC20实现。其中之一如下所示(其他名称和名称完全相同)

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

contract OldToken {
    string  public name = "Old Token";
    string  public symbol = "OLDT";
    uint256 public totalSupply = 1000000000000000000000000; // 1 million tokens
    uint8   public decimals = 18;

    event Transfer(
        address indexed _from,
        address indexed _to,
        uint256 _value
    );

    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint256 _value
    );

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    constructor() public {
        balanceOf[msg.sender] = totalSupply;
    }

    function transfer(address _to, uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
        emit Transfer(msg.sender, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) public returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= balanceOf[_from]);
        require(_value <= allowance[_from][msg.sender]);
        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;
        allowance[_from][msg.sender] -= _value;
        emit Transfer(_from, _to, _value);
        return true;
    }
}


2_deployed_token.js 如下所示。它还将一些 NewToken 转移到 GetNewToken 合同,并将一些 OldToken 转移到帐户[1],然后将其用于调用 buyTokens 函数。


const NewToken = artifacts.require("NewToken");
const OldToken = artifacts.require("OldToken");
const GetNewToken = artifacts.require("GetNewToken");

module.exports = async function(deployer, network, accounts) {
    await deployer.deploy(NewToken);
    const newToken = await NewToken.deployed();

    await deployer.deploy(OldToken);
    const oldToken = await OldToken.deployed();

    await deployer.deploy(GetNewToken, newToken.address, oldToken.address);
    const getNewToken = await GetNewToken.deployed();

    await newToken.transfer(GetNewToken.address, "1000000000000000000000"); // 1000 tokens
    await oldToken.transfer(accounts[1], "1000000000000000000000"); // 1000 tokens
};

truffle-config.js 如下:

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*"
    }
  },
  contracts_directory: './contracts/',
  contracts_build_directory: './abis/',
  compilers: {
    solc: {
      version: "0.6.2",
      optimizer: {
        enabled: true,
        runs: 200
      },
      evmVersion: "petersburg"
    }
  }
};

现在编译和迁移工作正常(我使用ganache作为本地区块链):

truffle compile
truffle migrate --reset

地址如下(以ganache为单位): 旧令牌 0xaA47e5555db895b230A16AF6860bf5DF442C7dB9

NewToken 0x43C68Efa858a9eA2F2DdD4e1AbDeA90a96f5C56E

GetNewToken 0x4b4a5d3Ad0ed472876e50FB0daa6ED2FA78488e2

以下是在松露控制台中执行的步骤:

NewToken.deployed().then(function(instance){newToken = instance})
OldToken.deployed().then(function(instance){oldToken = instance})

GetNewToken.deployed(newToken, oldToken).then(function(instance){return instance.buyTokens('1000000000000000000', {from:accounts[1]});});

然后返回错误:

Uncaught Error: Returned error: VM Exception while processing transaction: revert
    at evalmachine.<anonymous>:0:75
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  hijackedStack: 'Error: Returned error: VM Exception while processing transaction: revert\n' +
    '    at Object.ErrorResponse (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-core-helpers/src/errors.js:29:1)\n' +
    '    at /usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-core-requestmanager/src/index.js:140:1\n' +
    '    at /usr/local/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:112:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-providers-http/src/index.js:96:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)\n' +
    '    at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)\n' +
    '    at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:326:22)\n' +
    '    at IncomingMessage.EventEmitter.emit (domain.js:548:15)\n' +
    '    at endReadableNT (_stream_readable.js:1252:12)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:80:21)'

使用 truffle debug 0xdf7af41dd709d19a75b497c25cde854328ea50176c35c6661416a316c382d9ad 调试交易哈希,然后按 o 突出显示 GetNewToken 函数 buyTokens

debug(development:0xdf7af41d...)> o

Transaction halted with a RUNTIME ERROR.

There was no revert message.  This may be due to an in intentional halting expression, such as assert(), revert(), or require(), or could be due to an unintentional exception such as out-of-gas exceptions.
Please inspect your transaction parameters and contract code to determine the meaning of this error.

Stacktrace:
Error: Revert or exceptional halt
  at unknown function [address 0xaA47e5555db895b230A16AF6860bf5DF442C7dB9] (/Users/someuser/projects/project-folder/contracts/GetNewToken.sol:40:24)
  at GetNewToken.buyTokens [address 0x4b4a5d3Ad0ed472876e50FB0daa6ED2FA78488e2] (/Users/someuser/projects/project-folder/contracts/GetNewToken.sol:40:24)
  at GetNewToken [address 0x4b4a5d3Ad0ed472876e50FB0daa6ED2FA78488e2] (/Users/someuser/projects/project-folder/contracts/GetNewToken.sol:27:5)

Location of error:

GetNewToken.sol:
         
40:         bool success = oldToken.transferFrom(msg.sender, address(this), _amount);
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

debug(development:0xdf7af41d...)> o
Transaction has halted; cannot advance.

请忽略行号,因为GetNewToken.sol文件中的注释很少

  1. 为什么我不能使用transferFrom?帐户[1]已经具有OldTokens(根据迁移)。

  2. 此外,当我使用松露控制台时

truffle(development)> OldToken.deployed().then(function(instance){oldToken = instance})
truffle(development)> let a = oldToken.balanceOf(accounts[1])
undefined
truffle(development)> a
BN {
  negative: 0,
  words: [ 44040192, 40595831, 222044, <1 empty item> ],
  length: 3,
  red: null
}

为什么我没有得到1000000000000000000000(根据迁移脚本)?

谢谢!

0 个答案:

没有答案