I've created two smart contracts and both are deployed on Ropsten Test Network. I'm using MetaMask for transactions.
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); }
}
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);
}
}