1

I'm testing a Crowdsale contract (C) which send tokens of an already deployed contract (T). The idea is to send an amount of tokens to C from T, and then selling them for Ether, but nothing is working, C doesn't even receive the Ether. Here's the Crowdsale contract:

pragma solidity ^0.4.13;

contract ForeignToken {
    function balanceOf(address _owner) constant returns (uint256);
    function transfer(address _to, uint256 _value) returns (bool);
}

library SafeMath {
  function mul(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a / b;
    return c;
  }

  function sub(uint256 a, uint256 b) internal constant returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

contract Token { 
    function issue(address _recipient, uint256 _value) returns (bool success);
    function totalSupply() constant returns (uint256 supply);
    function unlock() returns (bool success);
}

contract TokenCrowdsale {

    using SafeMath for uint256;

    // Crowdsale details
    address public beneficiary;                     
    address public creator;                         
    address public confirmedBy;                     
    uint256 public maxSupply = 15000000e8;    
    uint256 public minAcceptedAmount = 10 finney;   
    bool public purchasingAllowed = false;


    // Eth to token rate
    uint256 public rate = 2000;

    enum Stages {
        PreSale,
        InProgress,
        Ended,
        Withdrawn
    }

    Stages public stage = Stages.PreSale;

    // deployed token
    Token public deplToken;

    // Invested balances
    mapping (address => uint256) balances;

    /**
    * Throw if at stage other than current stage
    * 
    * @param _stage expected stage to test for
    */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    /**
    * Throw if sender is not beneficiary
    */
    modifier onlyBeneficiary() {
        require(beneficiary == msg.sender);
        _;
    }

    /** 
    * Get balance of `_investor` 
    * 
    * @param _investor The address from which the balance will be retrieved
    * @return The balance
    */
    function balanceOf(address _investor) constant returns (uint256 balance) {
        return balances[_investor];
    }


    function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
        purchasingAllowed = false;
        stage = Stages.Ended;
    }

    function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    /**
    * Constructor
    *
    * @param _tokenAddress The address of the token contact
    * @param _beneficiary  The address of the wallet for the beneficiary  
    * @param _creator      The address of the wallet for the creator 
    */
    function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
        deplToken = Token(_tokenAddress);
        beneficiary = _beneficiary;
        creator = _creator;
    }

    /**
    * For testing purposes
    *
    * @return The beneficiary address
    */
    function confirmBeneficiary() onlyBeneficiary {
        confirmedBy = msg.sender;
    }


    /**
    * Transfer raised amount to the beneficiary address
    */
    function withdraw() onlyBeneficiary atStage(Stages.Ended) {
        uint256 ethBalance = this.balance;
        beneficiary.transfer(ethBalance);
        stage = Stages.Withdrawn;
    }

    /**
    * Receives Eth and issue tokens to the sender
    */
    function () payable atStage(Stages.InProgress) {

        require(purchasingAllowed);

        address investor = msg.sender;
        uint256 received = (msg.value).div(10e8);

        // Enforce min amount
        require(received >= minAcceptedAmount);
        uint256 tokens = (received).mul(rate);

        require(tokens > 0);

        require(deplToken.issue(investor, tokens));

        balances[investor] = balances[investor].add(received);
        //raised += received;

        // Check totalSupply raised
        if (deplToken.totalSupply() >= maxSupply) {
            stage = Stages.Ended;
        }
    }

    function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
        ForeignToken token = ForeignToken(_tokenContract);
        uint256 amount = token.balanceOf(address(this));
        return token.transfer(beneficiary, amount);
    }
}

Any help is appreciated, thank you

EDIT: after suggestions in comments, I managed to receive ETH on the Crowdsale contract, but it is not issuing the tokens. Here's the code:

pragma solidity ^0.4.13;

contract ForeignToken {
    function balanceOf(address _owner) constant returns (uint256);
    function transfer(address _to, uint256 _value) returns (bool);
}

library SafeMath {
  function mul(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a / b;
    return c;
  }

  function sub(uint256 a, uint256 b) internal constant returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

contract Token { 
    function issue(address _recipient, uint256 _value) returns (bool success);
    function totalSupply() constant returns (uint256 supply);
    function unlock() returns (bool success);
}

contract TokenCrowdsale {

    using SafeMath for uint256;

    // Crowdsale details
    address public beneficiary;                     
    address public creator;                         
    address public confirmedBy;                     
    uint256 public maxSupply = 15000000e8;    
    uint256 public minAcceptedAmount = 10 finney;
    bool public purchasingAllowed = false;
    uint256 public totalSupply = 0;

    // Eth to token rate
    uint256 public rate = 2000;

    enum Stages {
        PreSale,
        InProgress,
        Ended,
        Withdrawn
    }

    Stages public stage = Stages.PreSale;

    // deployed token
    Token public deplToken;

    // Invested balances
    mapping (address => uint256) balances;

    /**
    * Throw if at stage other than current stage
    * 
    * @param _stage expected stage to test for
    */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    /**
    * Throw if sender is not beneficiary
    */
    modifier onlyBeneficiary() {
        require(beneficiary == msg.sender);
        _;
    }

    /** 
    * Get balance of `_investor` 
    * 
    * @param _investor The address from which the balance will be retrieved
    * @return The balance
    */
    function balanceOf(address _investor) constant returns (uint256 balance) {
        return balances[_investor];
    }


    function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
        purchasingAllowed = false;
        stage = Stages.Ended;
    }

    function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    /**
    * Constructor
    *
    * @param _tokenAddress The address of the token contact
    * @param _beneficiary  The address of the wallet for the beneficiary  
    * @param _creator      The address of the wallet for the creator 
    */
    function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
        deplToken = Token(_tokenAddress);
        beneficiary = _beneficiary;
        creator = _creator;
    }

    /**
    * For testing purposes
    *
    * @return The beneficiary address
    */
    function confirmBeneficiary() onlyBeneficiary {
        confirmedBy = msg.sender;
    }


    /**
    * Transfer raised amount to the beneficiary address
    */
    function withdraw() onlyBeneficiary atStage(Stages.Ended) {
        uint256 ethBalance = this.balance;
        beneficiary.transfer(ethBalance);
        stage = Stages.Withdrawn;
    }

    /**
    * Receives Eth and issue tokens to the sender
    */
    function () payable atStage(Stages.InProgress) {
        require(purchasingAllowed);

        if (msg.value >= 10 finney) {
            address investor = msg.sender;
            uint256 received = (msg.value).div(10e8);
            uint256 tokens = (received).mul(rate);
            balances[investor] = balances[investor].add(tokens);
            totalSupply = (totalSupply).add(tokens);
        }

        if (totalSupply >= maxSupply) {
            purchasingAllowed = false;
            stage = Stages.Ended;
        }

    }

    function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
        ForeignToken token = ForeignToken(_tokenContract);
        uint256 amount = token.balanceOf(address(this));
        return token.transfer(beneficiary, amount);
    }
}

As you can see, I changed the "require" in the fallback function with an "if" iteration

10
  • Can you elaborate on "what is not working"? Can you show us how you call functions? with web3? With your wallet? Nov 23, 2017 at 2:19
  • @AlxMrx it seems that your code is working...Did you try it using Mist?? Nov 23, 2017 at 8:21
  • Well, I deployed it on testnet (Rinkeby) with Mist, then I sent 15M tokens to it and launched the function "enablePurchasing"; but if I try to send ETH from another wallet nothing happens, the transaction returns a "Fail" status
    – user19489
    Nov 23, 2017 at 8:38
  • you have a glitch: fuddToken doesn´t exist Nov 23, 2017 at 11:22
  • Yeah sorry, it is correct in the deployed contract as deplToken, I pasted here an old code. Corrected now
    – user19489
    Nov 23, 2017 at 11:30

1 Answer 1

0

Following the suggestions and doing more research led me to find the solution. First of all I changed the

contract Token {}

to

interface Token {}

I also added an event that is then called by the fallback function to send tokens:

event sendTokens(address indexed to, uint256 value);

Finally, I cleaned the code of unused variable and added some other function not related to my problem, but useful to manage the crowdsale. Here's the final working code:

pragma solidity ^0.4.13;

contract ForeignToken {
    function balanceOf(address _owner) constant returns (uint256);
    function transfer(address _to, uint256 _value) returns (bool);
}

library SafeMath {
  function mul(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a / b;
    return c;
  }

  function sub(uint256 a, uint256 b) internal constant returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal constant returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

interface Token { 
    function transfer(address _to, uint256 _value) returns (bool);
    function totalSupply() constant returns (uint256 supply);
    function balanceOf(address _owner) constant returns (uint256 balance);
}

contract TokenCrowdsale {

    using SafeMath for uint256;

    // Crowdsale details
    address public beneficiary;                     
    address public creator;                         
    address public confirmedBy;                     
    uint256 public maxSupply = 15000000e8;    
    bool public purchasingAllowed = false;
    uint256 public totalSupplied = 0;

    // Eth to token rate
    uint256 public rate = 2000;

    enum Stages {
        PreSale, //0
        InProgress, //1
        Ended, //2 
        Withdrawn //3
    }

    Stages public stage = Stages.PreSale;

    // deployed token
    Token public deplToken;

    // Invested balances
    mapping (address => uint256) balances;

    /**
    * Throw if at stage other than current stage
    * 
    * @param _stage expected stage to test for
    */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    /**
    * Throw if sender is not beneficiary
    */
    modifier onlyBeneficiary() {
        require(beneficiary == msg.sender);
        _;
    }

    /** 
    * Get balance of `_investor` 
    * 
    * @param _investor The address from which the balance will be retrieved
    * @return The balance
    */
    function balanceOf(address _investor) constant returns (uint256 balance) {
        return balances[_investor];
    }


    function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
        purchasingAllowed = false;
        stage = Stages.Ended;
    }

    function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
        purchasingAllowed = true;
        stage = Stages.InProgress;
    }

    /**
    * Constructor
    *
    * @param _tokenAddress The address of the token contact
    * @param _beneficiary  The address of the wallet for the beneficiary  
    * @param _creator      The address of the wallet for the creator 
    */
    function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
        deplToken = Token(_tokenAddress);
        beneficiary = _beneficiary;
        creator = _creator;
    }

    /**
    * For testing purposes
    *
    * @return The beneficiary address
    */
    function confirmBeneficiary() onlyBeneficiary {
        confirmedBy = msg.sender;
    }


    event sendTokens(address indexed to, uint256 value);


    /**
    * Transfer raised amount to the beneficiary address
    */
    function withdraw() onlyBeneficiary atStage(Stages.Ended) {
        uint256 ethBalance = this.balance;
        beneficiary.transfer(ethBalance);
        stage = Stages.Withdrawn;
    }

    /**
    * Receives Eth and issue tokens to the sender
    */
    function () payable atStage(Stages.InProgress) {

        require(purchasingAllowed);
        if (msg.value == 0) { return; }
        uint256 weiAmount = msg.value;
        address investor = msg.sender;
        uint256 received = weiAmount.div(10e7);
        uint256 tokens = (received).mul(rate);

        if (msg.value >= 10 finney) {
            uint256 bonusToken = (tokens.div(100)).mul(20);
            tokens = tokens.add(bonusToken);
        }

        sendTokens(msg.sender, tokens);
        deplToken.transfer(investor, tokens);
        totalSupplied = (totalSupplied).add(tokens);

        if (totalSupplied >= maxSupply) {
            purchasingAllowed = false;
            stage = Stages.Ended;
        }

    }


    function tokensAvailable() constant returns (uint256) {
        return deplToken.balanceOf(this);
    }


    function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
        ForeignToken token = ForeignToken(_tokenContract);
        uint256 amount = token.balanceOf(address(this));
        return token.transfer(beneficiary, amount);
    }
}

I'm not sure if either "interface Token" or "event sendTokens", or both together, were the solutions, but it is working now; I can send ether and receive the deployed token. I've answered my own question so it will remain here as a solution if anyone else need something like this. Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.