1

i created and deployed these 2 below contracts, when i tried to send ether to the crowdsale contract it fails any idea what i'm doing wrong

error message

token https://ropsten.etherscan.io/address/0x33f61d5c9cf02d994d9fe474cc5e016b673d0d8c

crowdsale https://ropsten.etherscan.io/address/0x836e34a95c3fd8830298a84708e6747a8fe0111f

SimpleToken.sol

pragma solidity ^0.4.11;

/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
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) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        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 Owned {

    // The address of the account that is the current owner 
    address public owner;

    // The publiser is the inital owner
    function Owned() {
        owner = msg.sender;
    }

    /**
    * Access is restricted to the current owner
    */
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    /**
    * Transfer ownership to `_newOwner`
    *
    * @param _newOwner The address of the account that will become the new owner 
    */
    function transferOwnership(address _newOwner) onlyOwner {
        owner = _newOwner;
    }
}

// Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20
contract Token {
    /* This is a slight change to the ERC20 base standard.
    function totalSupply() constant returns (uint256 supply);
    is replaced with:
    uint256 public totalSupply;
    This automatically creates a getter function for the totalSupply.
    This is moved to the base contract since public getter functions are not
    currently recognised as an implementation of the matching abstract
    function by the compiler.
    */
    /// total amount of tokens
    uint256 public totalSupply;

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance);

    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _value) returns (bool success);

    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);

    /// @notice `msg.sender` approves `_spender` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of tokens to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _value) returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

/**
* Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
*
* Modified version of https://github.com/ConsenSys/Tokens that implements the 
* original Token contract, an abstract contract for the full ERC 20 Token standard
*/
contract StandardToken is Token {

    using SafeMath for uint;

    // Token starts if the locked state restricting transfers
    bool public locked;

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

    // token allowances
    mapping (address => mapping (address => uint256)) allowed;

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

    /** 
    * Send `_value` token to `_to` from `msg.sender`
    * 
    * @param _to The address of the recipient
    * @param _value The amount of token to be transferred
    * @return Whether the transfer was successful or not
    */
    function transfer(address _to, uint256 _value) returns (bool success) {

        // Unable to transfer while still locked
        require(!locked);

        // Check if the sender has enough tokens
        require(balances[msg.sender] >= _value);

        // Check for overflows
        require(balances[_to].add(_value) >= balances[_to]);

        // Transfer tokens
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);

        // Notify listners
        Transfer(msg.sender, _to, _value);
        return true;
    }

    /** 
    * Send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    * 
    * @param _from The address of the sender
    * @param _to The address of the recipient
    * @param _value The amount of token to be transferred
    * @return Whether the transfer was successful or not
    */
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {

        // Unable to transfer while still locked
        require(!locked);

        // Check if the sender has enough
        require (balances[_from] >= _value);

        // Check for overflows
        require(balances[_to].add(_value) >= balances[_to]);      

        // Check allowance
        require (_value <= allowed[_from][msg.sender]);

        // Transfer tokens
        balances[_to] = balances[_to].add(_value);
        balances[_from] = balances[_from].sub(_value);

        // Update allowance
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);

        // Notify listners
        Transfer(_from, _to, _value);
        return true;
    }

    /** 
    * `msg.sender` approves `_spender` to spend `_value` tokens
    * 
    * @param _spender The address of the account able to transfer the tokens
    * @param _value The amount of tokens to be approved for transfer
    * @return Whether the approval was successful or not
    */
    function approve(address _spender, uint256 _value) returns (bool success) {

        // Unable to approve while still locked
        require(!locked);

        // Update allowance
        allowed[msg.sender][_spender] = _value;

        // Notify listners
        Approval(msg.sender, _spender, _value);
        return true;
    }


    /** 
    * Get the amount of remaining tokens that `_spender` is allowed to spend from `_owner`
    * 
    * @param _owner The address of the account owning tokens
    * @param _spender The address of the account able to transfer the tokens
    * @return Amount of remaining tokens allowed to spent
    */
    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
    return allowed[_owner][_spender];
    }
}

/**
* @title SMP (Simple Token) token
*
* Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
* with the addition of ownership, a lock and issuing.
*
*/
contract SMPToken is Owned, StandardToken {

    // Ethereum token standaard
    string public standard = "Token 0.1";

    // Full name
    string public name = "Simple Token";        

    // Symbol
    string public symbol = "SMP";

    // No decimal points
    uint8 public decimals = 8;

    // max token supply to mint
    uint256 maxSupply = 100000000 * 10**8;

    /**
    * Starts with a total supply of zero and the creator starts with 
    * zero tokens (just like everyone else)
    */
    function SMPToken() {  
        balances[msg.sender] = 0;
        totalSupply = 0;
        locked = true;
    }

    /**
    * locks the token irreversibly so that the transfering of value is disabled 
    *
    * @return Whether the locking was successful or not
    */
    function lock() onlyOwner returns (bool success) {
        locked = true;
        return true;
    }

    /**
    * Unlocks the token irreversibly so that the transfering of value is enabled 
    *
    * @return Whether the unlocking was successful or not
    */
    function unlock() onlyOwner returns (bool success) {
        locked = false;
        return true;
    }

    /**
    * Issues `_value` new tokens to `_recipient` (_value < 0 guarantees that tokens are never removed)
    *
    * @param _recipient The address to which the tokens will be issued
    * @param _value The amount of new tokens to issue
    * @return Whether the approval was successful or not
    */
    function issue(address _recipient, uint256 _value) onlyOwner returns (bool success) {

        // Guarantee positive 
        require(_value > 0);

        _value = _value * 10**8;

        // Guarantee totalSupply does not exceed maxSupply
        require(totalSupply.add(_value) <= maxSupply);

        // Create tokens
        balances[_recipient] = balances[_recipient].add(_value);
        totalSupply = totalSupply.add(_value);

        // Notify listners
        Transfer(0, owner, _value);
        Transfer(owner, _recipient, _value);

        return true;
    }

    /**
    * Prevents accidental sending of ether
    */
    function () payable {
        revert(); // throw;
    }
}

SimpleTokenCrowdSale.sol

pragma solidity ^0.4.11;

/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
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) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        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 SMPCrowdsale {

    using SafeMath for uint;

    // Crowdsale details
    address public beneficiary;                     // Company address multisig
    address public creator;                         // Creator 
    address public confirmedBy;                     // Address that confirmed beneficiary
    uint256 public minAmount = 2000 ether;          // 4 mil Token
    uint256 public maxSupply = 90000000 * 10**8;    // 90 mil Token
    uint256 public minAcceptedAmount = 10 finney;   // 1/10 ether

    // crowd sale end
    uint256 public lastWeekEnd = 51 days;

    // Eth to SMP rate
    uint256 public rateICO = 1500 * 10**8;

    enum Stages {
        InProgress,
        Ended,
        Withdrawn
    }

    Stages public stage = Stages.InProgress;

    // Crowdsale state
    uint256 public start;
    uint256 public end;
    uint256 public raised;

    // SMP token
    Token public smpToken;

    // 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];
    }

    /**
    * Constructor
    *
    * @param _tokenAddress The address of the Simple token contact
    * @param _beneficiary  The address of the wallet for the beneficiary  
    * @param _creator      The address of the wallet for the creator 
    * @param _start        Start time in epoch e.g. 1504224000 for 1st SEP 2017 00:00 UTC
    */
    function SMPCrowdsale(address _tokenAddress, address _beneficiary, address _creator, uint256 _start) {
        smpToken = Token(_tokenAddress);
        beneficiary = _beneficiary;
        creator = _creator;
        start = _start;
        end = start + lastWeekEnd;
    }

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

    /**
    * Function to end the crowdsale by setting the stage to Ended
    */
    function endCrowdsale() atStage(Stages.InProgress) {

        // Crowdsale not ended yet
        require (now >= end);

        stage = Stages.Ended;
    }

    /**
    * Transfer raised amount to the beneficiary address
    */
    function withdraw() onlyBeneficiary atStage(Stages.Ended) {

        // Confirm that minAmount is raised
        require(raised >= minAmount);

        uint256 ethBalance = this.balance;

        beneficiary.transfer(ethBalance);

        stage = Stages.Withdrawn;
    }

    /**
    * Refund in the case of an unsuccessful crowdsale. The 
    * crowdsale is considered unsuccessful if minAmount was 
    * not raised before end
    */
    function refund() atStage(Stages.Ended) {

        // Only allow refunds if minAmount is not raised
        assert(raised < minAmount);

        address investor = msg.sender;

        uint256 receivedAmount = balances[investor];
        balances[investor] = 0;
        require(receivedAmount > 0);
        investor.transfer(receivedAmount);        
    }

    /**
    * Receives Eth and issue SMP tokens to the sender
    */
    function () payable atStage(Stages.InProgress) {
        // is Crowdsale started 
        require(now >= start);

        // Crowdsale expired
        require(now <= end);

        address investor = msg.sender;
        uint256 received = msg.value; // wei Amount

        // Enforce min amount
        require(received >= minAcceptedAmount);
        uint256 tokens = received * rateICO;

        require(tokens > 0);

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

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

        // Check totalSupply raised
        if (smpToken.totalSupply() >= maxSupply) {
            stage = Stages.Ended;
        }
    }
}
  • I guess, that it's not probably the issue, but why this operation is not performed with math safe? in Token.issue _value = _value * 10**8; – Lukasz Zuchowski Sep 5 '17 at 7:52
3

SMPCrowdsale contract is calling the following function of the SMPToken contract:

function issue(address _recipient, uint256 _value) onlyOwner returns (bool success)

This function is protected by onlyOwner modifier, and in particular it throws an exception if the caller is not the owner of the contract.

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

Note that you are the owner of both contracts, but when the function is called msg.sender value is the address of the SMPCrowdsale contract, so it correctly throws an exception.

To quick fix this: use the transferOwnership(address _newOwner) function of the SMPToken contract to transfer the ownership of the token contract to the crowdsale one.

Please note that, even if it works fine after the change, I didn't audited all the contract functions, so read carefully all contract's code to understand if changing ownership is really what you want.

0

On the screen above the gas limit 122000 seems quite low. Maybe that is the issue?

EDIT: The other issue I see here is a probably some error in conversion. 1 Ether is 1*10^18 then it's multiplicated by ICO ratio 1,5 * 10^11 = 1,5 * 10^29 and then in Token.issue is multiplicated again by 10^8, so it would be 1,5*10^37 of simple tokens, but the max supply is 9*10^18.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.