I am making a test token on remix with Ganache open on my computer. I'll paste the code below and then to the questions and error. I got here by combining some samples online and fixing a few errors as they came up.
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address tokenOwner) external view returns (uint256 balance);
function allowance(address tokenOwner, address spender) external view returns (uint256 remaining);
function transfer(address to, uint tokens) external returns (bool success);
function approve(address spender, uint tokens) external returns (bool success);
function transferFrom(address from, address to, uint256 tokens) external returns (bool success);
event Transfer(address indexed from, address indexed to, uint256 tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint256 tokens);
}
// ----------------------------------------------------------------------------
// Safe Math Library
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a); c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
c = a * b; require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
require(b > 0);
c = a / b;
}
}
contract TTKN is IERC20, SafeMath {
string public name;
string public symbol;
uint8 public decimals; // 18 decimals is the strongly suggested default, avoid changing it
uint256 public _totalSupply;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
/**
* Constrctor function
*
* Initializes contract with initial supply tokens to the creator of the contract
*/
constructor() {
name = "Test Token";
symbol = "TTKN";
decimals = 18;
_totalSupply = 100000000000000000000000000;
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
function totalSupply() public view returns (uint256) {
return _totalSupply - balances[address(0)];
}
function balanceOf(address tokenOwner) public view returns (uint256 balance) {
return balances[tokenOwner];
}
function allowance(address tokenOwner, address spender) public view returns (uint256 remaining) {
return allowed[tokenOwner][spender];
}
function approve(address spender, uint256 tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transfer(address to, uint256 tokens) public returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function transferFrom(address from, address to, uint256 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);
emit Transfer(from, to, tokens);
return true;
}
}
So deploying works, calling totalSupply()
works and show that the address which deployed it (owner) has all the supply, cool. balanceOf()
, also good. And I can transfer to other accounts on my Ganache test network, via transfer()
from the owner.
I transfer from owner to addr1, then I try transferFrom()
addr2 to a new addr2, and I get the error below:
Clearly addr1 (the 0xD97...) has enough balance to send the required amount to addr2. In Ganache, all these accounts have close to 100 ETH as well. The error is below when transferFrom()
is clicked:
The console aftermath when I click send:
So I have a few questions here,
In general, is my token starter code sufficient? Anything I should change just to get the barebones functionality of create tokens, send tokens?
The error above: why can't addr2 send to addr3 with
transferFrom()
? The owner addr cannot call this function eitherWhat is all this
allowance
code? It is from templated code I am using, I don't understand this particular portion though. Is it really necessary? I just want to be able to send coins, I figure Metamask or similar will ask the user to confirm anyways.How do new tokens like this get 'wallets'? E.g. right now I can't view my Token's balance for any of these addresses in Ganache, all I can do is use the remix tools. I suppose I can make a website and use
web3
to interact with my contract. If/when this contract is eventually deployed to the mainnet, how can someone with e.g. an Exodus wallet add this token to their wallet?Wallets and addresses: other ERC20 tokens have unique addresses for their tokens, but for now what I can see with Ganache, it's just using the default Ethereum address. Surely for this contract (token) users should have a new address specific to my token?
Thanks so much to the Ethereum community, really great stuff!