Transacción revertida durante la ejecución del contrato [Revertida]

Envié ETH a una dirección de contrato y la transacción "falló" diciendo: Warning! Error encountered during contract execution [Reverted].

dirección del contrato y falla de la transacción aquí:

https://rinkeby.etherscan.io/tx/0x28a0a0f7eb8cf863afb4a9a2425648d2d9693e39793f0f9cc01d006374808370

Código de contrato de token ICO: -

pragma solidity ^0.4.24;
import "./DappToken.sol";


contract ICOToken is DappToken {

   string public name = 'ICOToken';
   string public symbol = 'ITK';
   uint256 public decimals = 18;
   uint256 public totalSupply;
   address public crowdsaleAddress;
   address public owner;
   uint256 public ICOEndTime = 1541246755;
   uint256 public balance;

   modifier onlyCrowdsale {
      require(msg.sender == crowdsaleAddress);
      _;
   }

   modifier onlyOwner {
      require(msg.sender == owner);
      _;
   }

//   modifier afterCrowdsale {
//  require(now > ICOEndTime || msg.sender == crowdsaleAddress);
//      _;
//  }

   constructor (uint256 _tokenSupply) public DappToken() {
      totalSupply = _tokenSupply;
      balanceOf[msg.sender] = _tokenSupply;
      owner = msg.sender;
   }


   function setCrowdsale(address _crowdsaleAddress) public onlyOwner  {

      require(_crowdsaleAddress != address(0));
      crowdsaleAddress = _crowdsaleAddress;

   }


    function buyTokens(address _receiver, uint256 _amount) public  {

      require(_receiver != address(0));
      require(_amount > 0);
      transfer(_receiver, _amount);


   }

//       /// @notice Override the functions to not allow token transfers until the end of the ICO
//   function transfer(address _to, uint256 _value) public afterCrowdsale returns(bool) {

//       return super.transfer(_to, _value);

//   }


//   /// @notice Override the functions to not allow token transfers until the end of the ICO
//   function transferFrom(address _from, address _to, uint256 _value) public afterCrowdsale returns(bool) {

//       return super.transferFrom(_from, _to, _value);

//   }


//   /// @notice Override the functions to not allow token transfers until the end of the ICO
//   function approve(address _spender, uint256 _value) public afterCrowdsale returns(bool) {

//       return super.approve(_spender, _value);
//   }

//   /// @notice Override the functions to not allow token transfers until the end of the ICO

//   function increaseApproval(address _spender, uint _addedValue) public afterCrowdsale returns(bool success) {

//       return super.increaseApproval(_spender, _addedValue);
//   }

//   /// @notice Override the functions to not allow token transfers until the end of the ICO

//   function decreaseApproval(address _spender, uint _subtractedValue) public afterCrowdsale returns(bool success) {

//       return super.decreaseApproval(_spender, _subtractedValue);
//   }

//   function emergencyExtract() external onlyOwner {

//       owner.transfer(address(this).balance);
//   }

}

Código de contrato de Crowdsale como este: -

    pragma solidity ^0.4.24;
import "./ICOToken.sol";

contract Crowdsale {
   bool public icoCompleted;
   uint256 public icoStartTime = 1538567825; // 3 oct 2018 11.57 AM UTC;
   uint256 public icoEndTime = 1541246755;  // 3 nov 2018 11.57 Am UTC;
   uint256 public tokenRate;
   uint256 public fundingGoal;
   address public owner;
   ICOToken public token;
   uint256 public tokensRaised;
   uint256 public etherRaised;
   uint256 public etherUsed = msg.value;
   uint256 public tokensToBuy;


   modifier whenIcoCompleted {
      require(icoCompleted);
      _;
   }

    modifier onlyOwner {
      require(msg.sender == owner);
      _;
   }

   function () public payable {
       buy();
   }

     constructor(uint256 _tokenRate, address _tokenAddress, uint256 _fundingGoal) public {
      require(icoStartTime != 0 &&
      icoEndTime != 0 &&
      icoStartTime < icoEndTime &&
      _tokenRate != 0 &&
      _tokenAddress != address(0) &&
      _fundingGoal != 0);
      tokenRate = _tokenRate;
      token = ICOToken(_tokenAddress);
      fundingGoal = _fundingGoal;
      owner = msg.sender;
      etherUsed;
      tokensToBuy;
   }

    function buy() public payable {

    //   require(tokensRaised < fundingGoal);
    //   require(now < icoEndTime && now > icoStartTime);

      etherUsed = msg.value;

      tokensToBuy = etherUsed * (10 ** token.decimals()) / 1 ether * tokenRate;

    //   Check if we have reached and exceeded the funding goal to refund the exceeding tokens and ether

    //   if(tokensRaised + tokensToBuy > fundingGoal) {

    //      uint256 exceedingTokens = tokensRaised + tokensToBuy - fundingGoal;
    //      uint256 exceedingEther;

    // //   Convert the exceedingTokens to ether and refund that ether
    //      exceedingEther = exceedingTokens * 1 ether / tokenRate / token.decimals();

    //      msg.sender.transfer(exceedingEther);

    //     //   Change the tokens to buy to the new number
    //      tokensToBuy -= exceedingTokens;

    //     //   Update the counter of ether used
    //      etherUsed -= exceedingEther;

    //   }
      // Send the tokens to the buyer
      token.buyTokens(msg.sender, tokensToBuy);

      // Increase the tokens raised and ether raised state variables
      tokensRaised += tokensToBuy;
      etherRaised += etherUsed;
   }


   function extractEther() public whenIcoCompleted onlyOwner {
       owner.transfer(address(this).balance);
   }

}

También realicé la depuración en remix y descubrí que cuando el usuario final paga el monto con la billetera metamask, este valor de mensaje no se almacena en la variable etherused que se usa en el contrato inteligente de venta colectiva. Entonces el token no puede transferirse al receptor.

Entonces, ¿cómo puedo resolver este problema? Por favor, ayúdame.

Gracias.

Es imposible ayudar sin ver algún código relevante.
Actualicé mi pregunta, por favor revise.

Respuestas (1)

Parece que cuando buy()se ejecuta, invoca a token.buyTokens().

buyTokens()a su vez llama transfer(). La gran mayoría de las funciones de transferencia verifican los saldos de los usuarios antes de realizar la transferencia, por lo que supongo que su súper implementación también lo hace.

Como tal, dado que dentro transfer()de usted msg.senderestá el contrato de venta colectiva, el contrato de venta colectiva debe contener suficientes tokens para realizar esa transferencia, lo que no parece ser el caso.

Nuevamente actualicé mi pregunta, por favor verifique. Ya uso la función de respaldo.
@AnupamJain actualizó mi respuesta.
Hola Raghav, gracias por responder. Cómo transfiero un token a un contrato de token a un contrato de venta colectiva
Cuando estoy usando la dirección del propietario como dirección del destinatario, la transacción se realizó con éxito. Pero cuando verifico desde la dirección en rinkeby.etherscan.io y no encuentro el token apropiado, sucede porque no estoy usando la dirección de crowsale. Si no es así, ¿por qué el usuario final no encuentra el ether apropiado? Por favor ayúdame a resolver esta consulta.
Hola Raghav, muchas gracias. Ahora mi funcionalidad de contrato funciona bien. Cuando transfiero el token en la dirección de venta de cuervos. Y luego envíe ether a la dirección de venta de cuervos. Entonces la transacción es exitosa.