Ошибка передачи токена с возвратом

У меня есть ваша последняя версия контрактов и почти такой же пример, как у вас в Github https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/examples/SampleCrowdsale.sol — я использую Ganache для тестирования на ОС MAC . И контракт работает только когда я комментирую строку

function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
    //token.transfer(_beneficiary, _tokenAmount);
  }

если это не прокомментировано, я получил ошибку времени выполнения и вернулся.

Мой простой код выглядит следующим образом:

ТОКЕН

pragma solidity ^0.4.18;

import 'zeppelin-solidity/contracts/token/ERC20/MintableToken.sol';

/**
 * The LeonardianToken contract does this and that...
 */
contract LeonardianToken is MintableToken {

    uint256 public constant INITIAL_SUPPLY = 10000;


    string public constant name = "Leonardian"; // solium-disable-line uppercase
    string public constant symbol = "LEON"; // solium-disable-line uppercase
    uint8 public constant decimals = 18; // solium-disable-line uppercase
}

ДОГОВОР:

pragma solidity ^0.4.18;

import 'zeppelin-solidity/contracts/crowdsale/validation/TimedCrowdsale.sol';
import "zeppelin-solidity/contracts/crowdsale/Crowdsale.sol";
import './LeonardianToken.sol';

contract LeonardianCrowdsale is Crowdsale {

    function LeonardianCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet, MintableToken _token) public 
    Crowdsale(_rate, _wallet, _token)
    // TimedCrowdsale(_startTime, _endTime)
    {

    }
}

МИГРАЦИЯ (без ошибок):

var LeonardianCrowdsale = artifacts.require("./LeonardianCrowdsale.sol");
var LeonardianToken = artifacts.require("./LeonardianToken.sol");

module.exports = function(deployer) {

  deployer.deploy(LeonardianToken).then(function () {

    const startTime = Math.round((new Date(Date.now() - 86400000).getTime())/1000); // Yesterday
    const endTime = Math.round((new Date().getTime() + (86400000 * 20))/1000); // Today + 20 days
    var exchangeRate = 1; // 1 LEON = 0.0025 ETH or 1 ETH = 400 LEON

    deployer.deploy(LeonardianCrowdsale, 
        startTime, 
        endTime,
        exchangeRate, 
        "0x627306090abaB3A6e1400e9345bC60c78a8BEf57", // Replace this wallet address with the last one (10th account) from Ganache UI. This will be treated as the beneficiary address. 
        LeonardianToken.address
      );
  });

};

Можете ли вы помочь мне, что я делаю неправильно?

РЕШЕНИЕ

Как уже упоминалось, ERC20 _token = new LeonardianToken(); должен быть включен в контракт Crowdsale, и важно, чтобы все работало после этого, - немного изменить вашу миграцию.

return deployer
    .then(() => {
        return deployer.deploy(Token);
    })
    .then(() => {

        return deployer.deploy(
            Crowdsale,
            startTime,
            endTime,
            exchangeRate,
            "wallet",
            Token.address
        );
    })
    .then(() => {

        var token = Token.at(Token.address);

        token.transferOwnership(Crowdsale.address);
    });

Ответы (1)

Токен должен быть развернут отдельно от Crowdsale и должен быть включен в Crowdsale.

pragma solidity ^0.4.18;

import 'zeppelin-solidity/contracts/crowdsale/validation/TimedCrowdsale.sol';
import "zeppelin-solidity/contracts/crowdsale/Crowdsale.sol";
import './LeonardianToken.sol';

contract LeonardianCrowdsale is Crowdsale {

    ERC20 _token = new LeonardianToken();

    function LeonardianCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet, MintableToken _token) public 
    Crowdsale(_rate, _wallet, _token)
    // TimedCrowdsale(_startTime, _endTime)
    {

    }
}
Я сталкиваюсь с этой же проблемой. Как получить адрес этого развернутого токена извне и убедиться, что это правильный экземпляр?
На самом деле я только что попробовал это решение. Кажется, это работает, потому что не выдает решение, но на самом деле не решает проблему. Это связано с тем, что экземпляр развернутого контракта не совпадает с экземпляром, созданным в файле массовой продажи. Таким образом, вызов withdrawTokensне генерирует исключение, но также неправильно передает токены.
добавляю правильное решение вопроса