Post your code here for the ERC20 Assignment.
Here is my solution:
pragma solidity 0.8.0;
import "./SafeMath.sol";
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
using SafeMath for uint256;
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
// Check so that the user has enough funds to spend
require(balances[msg.sender] >= _value);
// Use safe math to move the balance from senter to receiver
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
// Emit the event
emit Transfer(msg.sender, _to, _value);
// return true
_success = true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
// Allow the provided address of the spender to spend the specified amount
allowed[msg.sender][_spender] = _value;
// Emit the approve event
emit Approval(msg.sender, _spender, _value);
// Return true
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
// Make sure that there are enough funds in the from balance and that the caller is allowed to spend the specified amount
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
// Remove the spent amount from the allowance using safe math
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
// Use safe math to move the balance from senter to receiver
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
// Emit the transfer event
emit Transfer(_from, _to, _value);
// Return true
_success = true;
}
}
Done.
ERC20Assignment, Transfer, Approval, TransferTo
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
import "./SafeMath.sol";
contract Token {
using SafeMath for uint256;
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public payable returns (bool _success){
require(balances[msg.sender] >= _value, "Insufficient funds!"); //Checks for sufficient balance of msg.sender
uint prevBalanceSender = balances[msg.sender]; //saves balance of msg.sender before transfer
uint prevBalanceRecipient = balances[_to]; //saves balance of recipient before transfer
balances[msg.sender] = balances[msg.sender].sub(_value); //subtracts _value of transfer from balance of msg.sender
balances[_to] = balances[_to].add(_value); //adds _value to balance of recipient
assert(balances[msg.sender] == prevBalanceSender.sub(_value)); //asserts that new balance of msg.sender is previous balance minus _value
assert(balances[_to] == prevBalanceRecipient.add(_value)); //asserts that new balance of recipient is previous balance plus _value
return _success = true; //returns _success true if all goes well
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
allowed[msg.sender][_spender] = _value; // sets an approval for _spender to use _value amount of tokens from msg.sender's account
emit Approval(msg.sender, _spender, _value); // Emits event that new approval has been set
return _success = true; // returns true if all goes right
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(balances[_from] >= _value, "Insufficient funds!"); //Check for sufficient funds in _from address
require(allowed[_from][msg.sender] >= _value, "Not allowed to send this amount!"); //Check for sufficient allowance
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); //Decrease allowance by _value
balances[_from] = balances[_from].sub(_value); //Decrease _from address by _value
balances[_to] = balances[_to].add(_value); //Increase _to address by _value
emit Transfer(_from, _to, _value); //emits Transfer event
return _success = true; //returns true if successful
}
}
Here is my ERC-20 solution!
// https://eips.ethereum.org/EIPS/eip-20
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0 <=0.8.1;
interface Token {
/// @notice Determines the total number of tokens created minus the balance of the contract owner
/// @return total total number of tokens in circulation
function totalSupply() external view returns(uint256 total);
/// @param _owner The address from which the balance will be retrieved
/// @return balance the balance
function balanceOf(address _owner) external view 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 success Whether the transfer was successful or not
function transfer(address _to, uint256 _value) external 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 success Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
/// @notice `msg.sender` approves `_addr` to spend `_value` tokens
/// @param _spender The address of the account able to transfer the tokens
/// @param _value The amount of wei to be approved for transfer
/// @return success Whether the approval was successful or not
function approve(address _spender, uint256 _value) external 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 remaining Amount of remaining tokens allowed to spent
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
library 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 MatthewToken is Token {
//Attach safemath functions to uin256 variables
using SafeMath for uint256;
//Three optional variables
string internal name;
string internal symbol;
uint8 internal decimals;
//Total number of tokens
uint256 internal _totalSupply;
//Mapping of addresses to balances
mapping(address => uint256) balances;
//Mapping of owner addresses to a mapping of spenders and allowed amounts
mapping(address => mapping(address => uint256)) allowed;
constructor (string memory _name, string memory _symbol, uint8 _decimals, uint256 _initialOwnerBalance) {
name = _name;
symbol = _symbol;
decimals = _decimals;
_totalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// Six mandatory functions
//Determines the total number of tokens created minus the balance of the contract owner
function totalSupply() public override view returns(uint256 total) {
return _totalSupply - balances[address(0)];
}
//Returns the number of tokens that a particular address has
function balanceOf(address _owner) public override view returns(uint256 balance) {
return balances[_owner];
}
//Returns the number of tokens allowed by the owner to be spent by the spender
function allowance(address _owner, address _spender) public override view returns(uint256 remaining) {
return allowed[_owner][_spender];
}
//Contract owner can give their approval to an address to spend a given amount of their tokens on their behalf
function approve (address _spender, uint256 _value) public override returns(bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
//Contract owner can send a given amount of tokens to another address
//If the requested amount is greater than the owner's balance, an error will be thrown
function transfer(address _to, uint256 _value) public override returns (bool success) {
balances[msg.sender] = balances[msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd( _value);
emit Transfer(msg.sender, _to, _value);
return true;
}
//This function helps to automate transfers to and from specfic accounts
//If the requested value is greater than what is allowed by the owner, an error will be thrown
function transferFrom (address _from, address _to, uint256 _value) public override
returns (bool success) {
balances[_from] = balances[_from].safeSub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd(_value);
emit Transfer(_from, _to, _value);
return true;
}
}
pragma solidity 0.8.0;
import "./SafeMath.sol";
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
using SafeMath for uint;
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(balances[msg.sender] >= _value, "Insufficient funds");
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(balances[_from] >= _value, "Insufficient funds");
require(allowed[_from][msg.sender] >= _value, "Insufficient allowed funds");
balances[_from] = balances[_from].sub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
}
}
Hello! I think I overcomplicated the code at first. This is what I reduced it down to. Thanks for checking or any recommendations
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require ( balances[msg.sender] >= _value, "Insuffecient balance");
require ( _to != msg.sender, "You can't send to yourself");
balances[msg.sender].sub(_value);
balances[_to].add(_value);
emit Transfer( msg.sender, _to, _value);
return true;
}
function approve(address _spender,uint256 _value) public returns (bool _success) {
require ( msg.sender != _spender, "You don't need permission to send your own funds");
allowed[msg.sender][_spender] = _value;
emit Approval( msg.sender, _spender, _value);
return true;
}
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
return allowed[_owner][_spender];
}
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require( allowed[_from][msg.sender] <= _value, "You don't have permission to send this amount.");
require( balances[_from] <= _value, "Account has insuffecient balance.");
require( _from != _to, "From and to address are the same");
balances[_from].sub(_value);
allowed[_from][msg.sender].sub(_value);
balances[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
Well done here!
I also like that you used SafeMath as I come from really old Solidity versions and I am very used to it.
Just form Solidity 0.8, also normal (+ - : *) operators checks for overflows, so SafeMath is not needed anymore.
Happy coding,
Dani
Hey @Bhujanga
Your code is correct!
Just few tips:
- Avoid variable declaration when not needed;
- Avoid asserts when not needed.
Both of them use lots of gas.
assert(balances[msg.sender] == prevBalanceSender.sub(_value)); //asserts that new balance of msg.sender is previous balance minus _value
assert(balances[_to] == prevBalanceRecipient.add(_value));
Well done!
Dani
You are missing some important checks in your code.
Make sure to verify the sender balance before transferring funds.
function transfer(address _to, uint256 _value) public override returns (bool success) {
balances[msg.sender] = balances[msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd( _value);
emit Transfer(msg.sender, _to, _value);
return true;
}
With the function above, any user can send any amount of tokens even if he does not own any of them.
Same thing for transferFrom
Cheers,
Dani
Hey @NextGen33
Check these two require statements you posted, can you spot the issue?
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require( allowed[_from][msg.sender] <= _value, "You don't have permission to send this amount.");
require( balances[_from] <= _value, "Account has insuffecient balance.");
Cheers,
Dani
Thank you for catching that! How’s this?
//Msg.sender can send a given amount of tokens to another address
//If the requested amount is greater than the owner's balance, an error will be thrown
function transfer(address _to, uint256 _value) public override returns (bool success) {
require(balances[msg.sender] >= _value, 'Insufficient funds for transfer');
balances[msg.sender] = balances[msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd( _value);
emit Transfer(msg.sender, _to, _value);
return true;
}
//This function helps to automate transfers to and from specific accounts
//If the requested value is greater than what is allowed by the owner, an error will be thrown
function transferFrom (address _from, address _to, uint256 _value) public override
returns (bool success) {
require(allowed[_from][msg.sender] >= _value, 'Requested transfer amount exceeds allowance by token owner');
balances[_from] = balances[_from].safeSub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd(_value);
emit Transfer(_from, _to, _value);
return true;
}
Almost good, a check if missing in your transferFrom
You are checking if allowance is enough to send the tokens, but you should also make sure that ‘from’ has enough tokens
Cheers,
Dani
erc20-assignment.sol
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
//TEST CONSTRUCTOR
constructor() {
tokenName = "TRIFECTA-TOKEN";
tokenSymbol = "TRI3";
tokenDecimals = 8;
tokenTotalSupply = 100;
balances[msg.sender] = 100;
}
/*
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
*/
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply() external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
//msg.sender must have balance of tokens to send, note mapping is balance of tokens, NOT ether
require(balances[msg.sender] >= _value);
//make transfer and emit transfer event
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
_success = true;
}
/*
* @dev Allows _spender to withdraw/transfer from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
//msg.sender must have balance of tokens to send
require(balances[msg.sender] >= _value);
//address of _spender is allowed to allowance of _value to be spent from msg.sender balances, emit approve event
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
//require _from to have >balance and _spender to have >allowance than _value
require(balances[_from] >= _value);
require(allowed[_from][msg.sender] >= _value);
//transfer by deducting amount from owner balance and spender allowance, add to _to, emit event
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(_from, _to, _value);
_success = true;
}
}
My solution:
ERC20 Standard
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(_value <= balances[msg.sender], "Not enough funds");
require(_to != address(0), "Cant be zero address");
balances[msg.sender] = balances[msg.sender] - _value;
balances[_to] = balances[_to] + _value;
emit Transfer(msg.sender, _to, _value);
_success = true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
require(spender != address(0), "Cant be zero address");
allowed[msg.sender][spender] = _value;
emit Approval(msg.sender, spender, _value);
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(_value <= balances[_from], "Not enough funds");
require(_value <= allowed[_from][msg.sender], "Allowance limit");
require(_to != address(0), "Cant be zero address");
balances[_from] = balances[_from] - _value;
balances[_to] = balances[_to] + _value;
allowed[_from][msg.sender] = allowed[_from][msg.sender] - _value;
emit Transfer(_from, _to, _value);
_success = true;
}
}
Carlos Z
This is what i’ve cooked up…
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
_success = false;
require(balances[msg.sender] >= _value, "Balance not sufficient");
require(msg.sender != _to, "Don't transfer money to yourself");
balances[msg.sender]-=_value;
balances[_to]+=_value;
emit Transfer(msg.sender,_to,_value);
_success = true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
allowed[msg.sender][_spender]=_value;
emit Approval(msg.sender, _spender, _value);
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
//Check requirements, sufficient allowance, sufficient balance
require(_value <= allowed[_from][msg.sender], "Insufficient or no allowance");
require(balances[_from] >= _value, "Balance not sufficient");
//Update allowance
allowed[_from][msg.sender]-=_value;
//Make transfer
balances[_from]-=_value;
balances[_to]+=_value;
// emit and set _success
emit Transfer(_from,_to,_value);
_success = true;
}
}
Oh wow, how did I do that? lol thanks. I have to change <=_value to >=_value on both! Thanks for pointing that out
pragma solidity 0.8.0;
import "./safemath.sol";
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
using SafeMath for uint256;
event Transfer(address indexed _to, uint _amount);
event Approval(address indexed _spender, uint _value);
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(balances[msg.sender] >= _value, "Not enough value to transfer.");
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_to, _value);
return true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
require(balances[msg.sender] >= _value, "Not enough value to approve.");
allowed[msg.sender][_spender] = _value;
emit Approval(_spender,_value);
return true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(allowed[_from][msg.sender] >= _value, "Not enough value allowed to transfer.");
require(balances[_from] >= _value, "Owner has not enough value to send.");
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
}
}
Hey there, didn’t find the exact template FIlip was using in his videos so I started looking at the solutions in the forum. Here’s mine based on the solution of @thecil.
Just added some underscores that seemed to be missing in the _spender variable within the approve function.
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(_value <= balances[msg.sender], "Balance not enough");
require(_to != address(0), "Zero address!");
balances[msg.sender] = balances[msg.sender] - _value;
balances[_to] = balances[_to] + _value;
emit Transfer(msg.sender, _to, _value);
_success = true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
require(_spender != address(0), "Zero address!");
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(_value <= balances[_from], "Not enough funds");
require(_value <= allowed[_from][msg.sender], "Value over allowance limit");
require(_to != address(0), "Zero address!");
balances[_from] = balances[_from] - _value;
balances[_to] = balances[_to] + _value;
allowed[_from][msg.sender] = allowed[_from][msg.sender] - _value;
emit Transfer(_from, _to, _value);
_success = true;
}
}
My solution:
pragma solidity 0.8.0;
import "./SafeMath.sol";
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
using SafeMath for uint;
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(balances[msg.sender] >= _value, "Insufficient token balance");
balances[msg.sender].sub(_value);
balances[msg.sender].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(allowed[_from][msg.sender] >= _value, "You don't have approval for this amount on this address");
require(balances[_from] >= _value, "Insufficient balance");
balances[_from].sub(_value);
allowed[_from][_to].sub(_value);
balances[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
}
}
Here is my solution:
Click to View Code
pragma solidity 0.8.0;
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
require(balances[msg.sender] >= _value, "Insufficient Funds");
balances[_to] += _value;
balances[msg.sender] -= _value;
emit Transfer(msg.sender, _to, _value);
_success = true;
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
_success = true;
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
require(allowed[_from][msg.sender] >= _value, "Not allowed to spend this amount of tokens");
require(balances[_from] >= _value, "Insufficient funds");
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
_success = true;
}
}