首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >“处理事务时的VM异常:还原”在Truffle和Truffle中

“处理事务时的VM异常:还原”在Truffle和Truffle中
EN

Ethereum用户
提问于 2020-05-08 10:12:17
回答 2查看 2.8K关注 0票数 0

这是我的问题:)

问题

"Error:返回的错误:处理事务时的VM异常:还原“在到达传输函数时。我认为这与我的没有任何TotalSupply的令牌有关。

复制

的步骤

令牌智能契约:

代码语言:javascript
运行
复制
    pragma solidity   0.5.16; 

    import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol";
    import "openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol";

    contract TokenSPC is PausableToken, DetailedERC20 
    {

        constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _amount)
        DetailedERC20(_name, _symbol, _decimals)
        public
        {

            require(_amount > 0, "amount has to be greater than 0");
            totalSupply_ = _amount.mul(10 ** uint256(_decimals));
            balances[msg.sender] = totalSupply_;
            emit Transfer(address(0), msg.sender, totalSupply_);


        }
    } 

Crowdsale合同:

代码语言:javascript
运行
复制
    pragma solidity 0.5.16;

    import './TokenSPC.sol';
    import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
    import "openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol";
    import "openzeppelin-solidity/contracts/crowdsale/Crowdsale.sol";
    import "openzeppelin-solidity/contracts/crowdsale/validation/CappedCrowdsale.sol";


    contract TokenCrowdsale is Crowdsale, CappedCrowdsale {

      //Minim invest contrib
      //Max invest contrib
      uint256 public investorMinCap = 2000000000000000;
      uint256 public investorHardCap = 50000000000000000000;
      mapping(address => uint256) public contributions;

      constructor(
        uint256 _rate,
        address payable _wallet,
        ERC20 _token,
        uint256 _cap
       )
      Crowdsale(_rate, _wallet, _token)
      CappedCrowdsale(_cap)
      public
      {

      }

      function getUserContribution(address _beneficiary)
      public view returns(uint256)
      {
        return contributions[_beneficiary];
      }

      function _preValidatePurchase(
        address _beneficiary, 
        uint256 _weiAmount
     )
     internal
     {
        super._preValidatePurchase(_beneficiary,_weiAmount);
        uint256 _existingContribution = contributions[_beneficiary];
        uint256 _newContribution = _existingContribution.add(_weiAmount);
        require(_newContribution >= investorMinCap && _newContribution <= investorHardCap);
        contributions[_beneficiary] = _newContribution;
     } 
   }

测试Crowdsale.test:

代码语言:javascript
运行
复制
import ether from './helpers/ether';
import sendTransaction from './helpers/sendTransaction';
import EVMRevert from './helpers/EVMRevert';

const BN = web3.utils.BN;

require('chai')
  .use(require('chai-as-promised'))
  .use(require('chai-bn')(BN))
  .should();

const Token = artifacts.require('TokenSPC');
const TokenCrowdsale = artifacts.require('TokenCrowdsale');

contract('TokenCrowdsale', function([_, wallet, investor1, investor2]) {

  /*before(async function() {
    // Transfer extra ether to investor1's account for testing
    await web3.eth.sendTransaction({ from: _, to: investor1, value: ether(60) })
    await web3.eth.sendTransaction({ from: _, to: investor2, value: ether(20) })
  });*/

  beforeEach(async function () {
    // Token config
    this.name = "Seed Project Coin";
    this.symbol = "SPC";
    this.decimals = 18;
    this.amount = 380000000;


    // Deploy Token
    this.token = await Token.new(
      this.name,
      this.symbol,
      this.decimals,
      this.amount
    );

    // Crowdsale config
    this.rate = new BN(500);
    this.wallet = wallet;
    this.cap = ether(100);

    //Invest cap
    this.investorMinCap = ether(0.002);
    this.investorHardCap = ether(50);

    this.crowdsale = await TokenCrowdsale.new(
      this.rate,
      this.wallet,
      this.token.address,
      this.cap


    );

    // Transfer token owern to crowdsale
    await this.token.transferOwnership(this.crowdsale.address);


  });

  describe('token', function() {
    it("should check totalSupply", async function() {
      const _supp = await this.token.totalSupply();
      console.log( "     ", "totalSupply =", _supp.toString());
    });

  });

  describe('crowdsale', function() {
    it('tracks the rate', async function() {
      const _rate = await this.crowdsale.rate();
      //console.log( "     ", "Rate =", _rate );
      //console.log( "     ", "this.rate =", this.rate );
      _rate.should.be.a.bignumber.that.equals(this.rate);
    });

    it('tracks the wallet', async function() {
      const wallet = await this.crowdsale.wallet();
      wallet.should.equal(this.wallet);
    });

    it('tracks the token', async function() {
      const token = await this.crowdsale.token();
      token.should.equal(this.token.address);
    });
  });

  //A revoir---------------------------------------------
 /* describe('actualization crowdsale', function() {
    it('actualize total supply of crowdsale after purchase', async function() {
      const originalTotalSupply = await this.token.totalSupply();
      this.token.totalSupply_ -= 1;
      const newTotalSupply = await this.token.totalSupply();
      assert.isTrue(newTotalSupply < originalTotalSupply)
    });
  });*/

  describe('capped crowdsale', async function() {
    it('has the correct hard cap', async function() {
      const _cap = await this.crowdsale.cap();
      _cap.should.be.a.bignumber.that.equals(this.cap);
    });
  });

  //A revoir ---------------------------------------------
  /*describe('accepting payments', function() {
    it('should accept payments', async function() {
      const value = ether(1);
      const purchaser = investor2;
      await this.crowdsale.sendTransaction({ value : value, from : investor1}).should.be.fulfilled;
      await this.crowdsale.buyTokens(investor1, { value: value, from: purchaser }).should.be.fulfilled;
    });
  });*/

  describe('buyTokens()', function() {
    describe('when the contrib is less than min cap', function(){
      it('rejects the transaction', async function() {
        const value = this.investorMinCap - 1;
        await this.crowdsale.buyTokens(investor2, { value: value, from: investor2 }).should.be.rejectedWith(EVMRevert);
      });
    });

     describe('when the invest has already met the min cap', function(){
      it('allows the invest to contrib below the min cap', async function() {
        //isvalid
        const value1 = ether(1);


        await this.crowdsale.buyTokens(investor1, { value: value1, from: investor1 });
        console.log( "     ", "inv =", investor1 );
        console.log( "     ", "value =", value1 );
        console.log( "     ", "inv.value =", await this.crowdsale.buyTokens(investor1, { value: value1, from: investor1 }) );
        //is less then invest cap
        const value2 = 1; //wei
        await this.crowdsale.buyTokens(investor1, { value: value2, from: investor1 }).should.be.fulfilled;

      });
    });

  });

/*---------------A revoir
  describe('when the total contrib exceed the invest hardcap', function(){
    it('reject the transaction', async function() {
      //first contrib in valid range
      const value1 = ether(2);
      await this.crowdsale.buyTokens(investor1, { value: value1, from: investor1});

      //second is over hardcap
      const value2 = ether(49);
      await this.crowdsale.buyTokens(investor1, { value: value2, from: investor1}).should.be.rejectedWith(EVMRevert);
    });
  });

  describe('when the contrib is within the valid range', function() {
    const value = ether(2);
    it('succeeds & updates the contrib amount', async function() {
      await this.crowdsale.buyTokens(investor2, { value: value, from: investor2 }).should.be.fulfilled;
      const contribution = await this.crowdsale.getUserContribution(investor2);
      contribution.should.be.bignumber.equals;
    });
  });
*/

});

设计脚本:

代码语言:javascript
运行
复制
const Token = artifacts.require("./TokenSPC.sol");
const TokenCrowdsale = artifacts.require("./TokenCrowdsale.sol");

const ether = (n) => new web3.utils.BN(web3.utils.toWei(n.toString(), 'ether'));

const duration = {
  seconds: function (val) { return val; },
  minutes: function (val) { return val * this.seconds(60); },
  hours: function (val) { return val * this.minutes(60); },
  days: function (val) { return val * this.hours(24); },
  weeks: function (val) { return val * this.days(7); },
  years: function (val) { return val * this.days(365); },
};

module.exports = async function(deployer, network, accounts) {
  const _name = "Seed Project Coin";
  const _symbol = "SPC";
  const _decimals = 18;
  const _amount = 380000000;

  await deployer.deploy(Token , _name, _symbol, _decimals, _amount );
  const deployedToken = await Token.deployed();



  const _rate           = 1;
  const _wallet         = accounts[0]; // TODO: Replace me
  const _token          = deployedToken.address;
  const _cap            = ether(100);

  await deployer.deploy(
    TokenCrowdsale,
    _rate,
    _wallet,
    _token,
    _cap

  );

  return true;
};

第一个有错误的方法:

通过cmd:ganache-cli启动ganache-cli

编译:truffle compile

发射试验:truffle test ./test/TokenCrowdsale.test.js

第二个有错误的方法:

通过cmd:ganache-cli启动ganache-cli

编译:truffle compile

迁移:truffle migrate

使用控制台:truffle console

松露控制台中的命令:

代码语言:javascript
运行
复制
    - TokenSPC.deployed().then(instance => token = instance)
    - TokenCrowdsale.deployed().then(instance => crowdsale = instance)

    - web3.eth.getAccounts().then(function(acc){ accounts = acc }) 
    -  var tokenamount = 100 * 10**18 
    - token.transfer(accounts[1], tokenamount.toString())

    - crowdsale.buyTokens(accounts[1], { from: accounts[1], value: 10000000000000000000 })

期望行为

Crowdsale合同有一个固定的totalSupply,我不想要任何造币券。因此,我希望众包完成交易,购买令牌并将其转移给用户。

实际结果

环境

  • 操作系统: Windows 10
  • =>客户端: Ganache-cli => v6.9.1,Ganache-core => v2.10.2
  • 松露版本(truffle version):v5.1.20
  • 节点版本(node --version):v12.16.1
  • npm版本(npm --version):v6.13.4

更多信息

我正在学习DappUniversity : Real Ico的教程,以帮助我构建智能契约功能。我做了很多关于我遇到的错误的研究,并且几乎每次都能找到一个解决方案。但是VM错误是垃圾,什么都没说。而且,我没有发现任何类似我的问题。只有一个话题指出了这样一个事实:大多数情况下,如果不是汽油问题,那是因为我们没有任何令牌可买,这对我来说是正确的。我真的认为这是因为我在众筹中没有任何totalSupply,所以他不能买/转/等等.我被困住了,因为我找不到一个教程或主题来解释如何有固定的总供给。事实上,我的处境有一个问题,就是这个话题:

克劳德出售代币

但是他在大众销售合同的帮助下创造了象征性的合同,而我也不想这样做。我需要找到一种将totalSupply从令牌合同转移到众包合同的方法,并使用松露测试来测试它。

非常感谢你的帮助偷窥!

EN

回答 2

Ethereum用户

发布于 2020-05-13 10:45:13

您的集体销售合同没有任何代币可转让给买方。

您可以在测试文件中传输令牌契约的所有权,但是总供应量仍然控制着令牌契约部署器地址。从外观上看,它应该是您的帐户0。

在实例化了两个合同之后,您将需要执行如下操作:

await this.token.transfer(desiredAmountOfTokens, this.crowdsale.address)

票数 0
EN

Ethereum用户

发布于 2020-05-15 14:33:39

是的,我很确定这是因为你说我的销售合同没有供应。我本来希望从Token.sol script合同中进行转换,但实际上,我需要在测试脚本中完成吗?所以我不能让它成为一个自动的?我将需要手动转移供应从令牌到众销售后,他们的部署?

非常感谢你抽出时间来!

票数 0
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/83178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档