1

I've created two smart contracts and both are deployed on Ropsten Test Network. I'm using MetaMask for transactions.

  1. ERC20 token that has the implementation as below (please do note that I am able to see my tokens available in MetaMask):

    contract AppleToken is ERC20Interface, Owned, SafeMath {
    string public symbol;
    string public  name;
    uint8 public decimals;
    uint public _totalSupply;
    
    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;
    
    
    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    function AppleToken()  public {
        symbol = "AppleToken";
        name = "Apple Token";
        decimals = 18;
        _totalSupply = 100000000000000000000000000;
        balances[0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15] = _totalSupply;
        Transfer(address(0), 0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15, _totalSupply);
    }
    
    
    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public constant returns (uint) {
        return _totalSupply  - balances[address(0)];
    }
    
    
    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }
    
    
    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(msg.sender, to, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        Approval(msg.sender, spender, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Transfer tokens from the from account to the to account
    // 
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the from account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(from, to, tokens);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }
    
    
    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account. The spender contract function
    // receiveApproval(...) is then executed
    // ------------------------------------------------------------------------
    function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
        return true;
    }
    
    
    // ------------------------------------------------------------------------
    // Don't accept ETH
    // ------------------------------------------------------------------------
    function () public payable {
        revert();
    }
    
    
    // ------------------------------------------------------------------------
    // Owner can transfer out any accidentally sent ERC20 tokens
    // ------------------------------------------------------------------------
    function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
        return ERC20Interface(tokenAddress).transfer(owner, tokens);
    }
    

    }

  2. Another smart contract that receives Ether and it should interact with the above given smart contract to transfer my tokens to the sender of Ether.

I am trying to implement what's mentioned in point number 2, but if I try to access the "transfer" function of the ERC20 token instance, I get an error of gas estimation exceeding (I've tried increasing the gas limit, doesn't work). Also, when I try to force the transaction via MetaMask, it shows me the execution cost as 60001 eth, even when I'm trying to send just 1 ether.

Here is the implementation of my function

FOR NOW, I AM THE SENDER OF ETHER AND I AM THE RECEIVER OF THE ERC20 TOKENS

function sendTokens () public payable returns (uint)
    {
       //tokenAddress is the address of the ERC20 token deployed on Ropsten
        AppleToken appleToken;
        appleToken = AppleToken(tokenAddress);
        appleToken.transfer(msg.sender, 10);
        return appleToken.balanceOf(msg.sender);
    }

I'm sending hard coded 10 tokens at the moment for testing purposes. Note that I have included AppleToken with import "browser/AppleToken.sol";

If I execute ONLY the appleToken.balanceOf function, then it returns nothing. So to sum up, it is problematic on "transfer" function because of the overly calculated execution cost, and it returns nothing for "balanceOf", not even a 0.

Am I initiating the instance of AppleToken correctly? Or is there something else I'm doing wrong?

Any help would be appreciated.

Thank you.

UPDATE

Account public address on Ropsten: 0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15

ERC20 Token Address on Ropsten: 0x580156edb25D3c3deD584F1075CcCC5dA4861883

Following is the entire code of the EquityInvestments Contract:

I have removed unnecessary things in the code since I'm not calling those functions or using some variables defined for the problem I'm facing

pragma solidity ^0.4.16;
import "browser/AppleToken.sol";

contract EquityInvestments 
{
    AppleToken appleToken;
    Group [] _Groups;
    uint PriceEth = 1;
    address tokenAddress = 0x580156edb25D3c3deD584F1075CcCC5dA4861883;
    mapping (address => mapping(uint=>UserInvestment)) private _UserInvestments;

    function EquityInvestments () public
    {
        _Groups.push(Group({
            GroupID: 1,
            GroupName: "Google",
            TotalInvestment: 0,
            GroupPriceDollars: 200,
            GroupPriceEth: 1
        }));
         _Groups.push(Group({
            GroupID: 2,
            GroupName: "Tesla",
             TotalInvestment: 0,
             GroupPriceDollars: 200,
             GroupPriceEth: 1
        }));
         _Groups.push(Group({
            GroupID: 3,
            GroupName: "Apple",
             TotalInvestment: 0,
             GroupPriceDollars: 200,
             GroupPriceEth: 1
        }));
    }

    struct Group
    {
     uint GroupID;
     string GroupName;
     uint TotalInvestment;
     uint GroupPriceDollars;
     uint GroupPriceEth;
    }

    function sendTokens () public payable returns (uint)
    {
        appleToken = AppleToken(tokenAddress);
        // return appleToken.balanceOf(msg.sender);
        // appleToken.approve(this, 10);
        require(appleToken.transfer(msg.sender, 10));
        return appleToken.balanceOf(msg.sender);
    }



}
0

2 Answers 2

1

I can't see what's wrong with the token contract.

Concerning the second one, you should do :

function sendTokens () public payable returns (uint)
    {
        AppleToken appleToken = AppleToken(tokenAddress);
        require(appleToken.transfer(msg.sender, 10));
        return appleToken.balanceOf(msg.sender);
    }
  1. No need to declare the appleToken variable then set it, you can combine both.
  2. Be sure that tokenAddress is the correct one.
  3. Always use a require when doing token transfer! Do not think it works like the transfer method for ether, which handles failure and will throw for you.

EDIT :

I have tested the contracts and it works fine. I think you simply forgot to send tokens to the EquityInvestments contract, hence token balance of msg.sender staying at 0.

7
  • Still no luck. This is the error I see, was seeing it before too. "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? Error: gas required exceeds allowance or always failing transaction at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:18062:326 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:17305:855 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:400:2363 at u (chrome- ...." Apr 3, 2018 at 21:30
  • Can you give all the code + the addresses of the contracts on ropsten? Apr 3, 2018 at 21:45
  • Thank you for looking into this @Elisha, I've updated my question, please check. Apr 3, 2018 at 22:06
  • @MuradHasan Did you actually credit the EquityInvestments contract with tokens? Apr 3, 2018 at 22:17
  • @ElishaDion could you please elaborate? Because I'm not trying to send tokens to the EquityInvestments contract. This contract is just to accept Ether and should call the AppleToken contract's transfer function to send tokens to the address of msg.sender (which was received in the EquityInvestments contract) Apr 3, 2018 at 22:23
0

To elaborate on a comment by @elidrion, the .transfer method attached to contracts WILL SEND ETHER NOT TOKENS from message contract to owner.

For example to pull tokens out of a contract do not use global transfer method provided by solidity, do something like this:

function transferTokensOutOfTokenContract(uint tokens) public onlyOwner returns (bool success) {
        require(tokens <= balances[address(this)]);
        balances[address(this)] = balances[address(this)].sub(tokens);
        balances[msg.sender] = balances[msg.sender].add(tokens);
        emit Transfer(address(this), msg.sender, tokens);
        return true;
    }

Your Answer

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

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