Assignment - ERC20

ERC20 Assignment Attempt:

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;
      
      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){
      require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
      
      balances[_from] -= _value;
      balances[_to] += _value;
      allowed[_from][msg.sender] -= _value;
      
      emit Transfer(_from, _to, _value);
      _success = true;
  }
}
1 Like

Hi All!
Here is solution:

pragma solidity 0.8.0;
import "./safemath.sol";
...
contract Token {
    
  using SafeMath for uint256;
...

  /*
   * @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);
        require(msg.sender != _to);
        emit Transfer( msg.sender, _to, _value);
        
        //   uint toTransfer = balance[msg.sender];
        //   balances[msg.sender] = 0;
        //   (bool success, bytes memory data) = msg.sender.call{value:
        
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[msg.sender].add(_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, "ERR-001:TransferFrom:Not enough approval amount" );
        require(balances[_from] > _value, "ERR-002:TransferFrom:Not enough money on balance" ); 
        
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_from].add(_value); 
        
        emit Transfer( _from, _to, _value);
        
        return true; 
  }
}
1 Like

Here is my code:

  1. transfer
  function transfer(address payable _to, uint256 _value) public returns (bool _success){
      require(balances[msg.sender]>=_value, "Balance of sender insufficient to process the transfer!");
      balances[msg.sender]-=_value;
      balances[_to]+=_value;
      emit Transfer(msg.sender,_to,_value);
      return true;
  }
  1. approve
  function approve(address _spender,uint256 _value) public returns (bool _success) {
      require(balances[msg.sender]>=_value, "Balance of sender owner insufficient to process the transfer!");
      allowed[msg.sender][_spender]=_value;
      emit Approval(msg.sender, _spender, _value);
      return true;
  }
  1. transferFrom
  function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
      require(balances[_from]>=_value, "Balance of sender insufficient to process the transfer!");
      balances[_from]-=_value;
      balances[_to]+=_value;
      emit Transfer(_from,_to,_value);
      return true;
  }
1 Like
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 (balance[msg.sender] >= _value);
    balance[msg.sender] = balance[msg.sender].sub(_value);
    balance [_to] = balance[_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 (_value >= balances[msg.sender]);
    require (_value >= balances[_from][msg.sender]);
    
    balances[msg.sender]=balances[msg.sender].sub(_value);
    allowed[_from][msg.sender]=balances[msg.sender][_from].sub(_value);
    balances[_to]= balances[_to].add(_value);
    emit Transfer(_from, _to, _value);
    return true;
    
  }

}
1 Like

Ive tried to add a backup functionality in case the transfer fails as we’ve looked at in the Re-Entrancy lesson with Filip. I receive an Error message that I dont understand.

/*
    bool success = balances[msg.sender].sub(_value); && balances[_to].add(_value);;
    
    if(!success){
        balances[msg.sender].add(_value);
        balances[_to].add(_value);
        return("balance was corrected");
    }
    */

Error:
Error
where did I go wrong?

Code

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 {
  /*
   * Token name.
   */
   
  using SafeMath for uint;
  
  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 sufficient funds");
    balances[msg.sender].sub(_value);
    balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    _success = true;
    /*
    bool success = balances[msg.sender].sub(_value); && balances[_to].add(_value);;
    
    if(!success){
        balances[msg.sender].add(_value);
        balances[_to].add(_value);
        return("balance was corrected");
    }
    */
    }

  /*
   * @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(balances[_from] >= _value, "not enough funds on Account");
    balances[_from].sub(_value);
    balances[_to].add(_value);
    emit Transfer(_from, _to, _value);
    _success = true;
  }

}
1 Like

Forgot to subtract from the allowance at first but here’s the fixed version.

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){
      require(balances[msg.sender] >= _value);
      
      _transfer(msg.sender, _to, _value);

      _success = true;
  }
  
  function _transfer(address _from, address _to, uint256 _value) private{
      uint256 currentFromBalance = balances[_from];
      uint256 currentToBalance = balances[_to];
      
      balances[_from] = balances[_from].sub(_value);
      balances[_to] = balances[_to].add(_value);
      
      assert(balances[_from] == currentFromBalance - _value);
      assert(balances[_to] == currentToBalance + _value);
  }

  /*
   * @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(balances[_from] >= _value);
      require(allowed[_from][msg.sender] >= _value);
      
      _transfer(_from, _to, _value);
      allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);

      emit Transfer(_from, _to, _value);
      
      _success = true;
  }

}
1 Like

Here is my 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,"Bummer! Insufficient balance.");
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        _success = true;
        emit Transfer(msg.sender, _to, _value);
  }

  /*
   * @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;
        _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){
        uint remaining_limit = allowance(_from, msg.sender);
        require(remaining_limit) >= _value);
        require(balances[_from] >= _value);
        balances[_from] = balances[_from] - _value;
        balances[_to] = balances[_to] + _value;
        emit Transfer(_from,_to,_value);
        _success = true;
  }

}
1 Like
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], "insufficient balance");
     balances[msg.sender]-=value;
     balances[to]+=value;
     _success = true; 
     emit Transfer(msg.sender, _to, _value);
  }
/*
   * @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;
             _success = true;
             emit Approval(msg.sender, _spender, _value);
  }
/*
   * @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( approved[_from][msg.sender] >= _value, "not enough approval");
      require( balances[msg.sender] >= _value, "owner's balances are insufficient")
      approved[_from][msg.sender]-= _value;
      balances[_from]-=value;
      balances[_to]+=value;
      _success = true;
     emit Transfer(_from, _to, _value); 
     
  }
}
1 Like
function transfer(address payable _to, uint256 _value) public returns (bool _success){
      
      require(balances[msg.sender] >= _value);  // Check if enough tokens
     
      balances[msg.sender] -= _value; // effect
      balances[_to] += _value;   // effect
      
      emit Transfer(msg.sender, _to, _value);   //fire Transfer event
      
      return true;
  }

  function approve(address _spender, uint256 _value) public returns (bool _success) {
      
      allowed[msg.sender][_spender] = _value;
      
      emit Approval(msg.sender, _spender, _value);
      
      return true;

  }
  
  function transferFrom(address _from, address _to, uint256 _value) public returns (bool _success){
      
        require(_value <= balances[_from]);
        
        require(_value <= allowed[_from][msg.sender]);
        
        balances[_from] -= _value;
        
        allowed[_from][msg.sender] -= _value;
        
        balances[_to] += _value;
       
        emit Transfer(_from, _to, _value);
        
        return true;

  }

1 Like

Here are my functions:

transfer
  function transfer(address payable _to, uint256 _value) public returns (bool _success){
      require(balances[msg.sender]>= _value, "Not enough founds!"); //checks
      uint256 previousBalance = balances[msg.sender];
      balances[msg.sender] -= _value;
      balances[_to] += _value; //events
      assert(balances[msg.sender] == previousBalance - _value); //invariants
      emit Transfer(msg.sender,_to,_value); //interaction
      _success = true;
      
  }

approve
  /*
   * @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;
  }

transferFrom
/*
   * @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, "Not enough funds!" );
      require(allowed[_from][msg.sender] >= _value, "Amount not allowed"); //checks
      uint256 previousBalance = balances[_from];
      balances[_from] -= _value;
      balances[_to] += _value;
      allowed[_from][msg.sender] -= _value; // eventes

      assert(previousBalance == balances[_from] + _value); //invariants
      emit Transfer(_from, _to, _value); //interaction
      _success = true;
  }

I do have one doubt about using asserts in this use case, I know that they consume a lot of gas, and these operations are pretty simple but due that we are talking about balances and things that can impact real value, not 100% sure that this is the correct use case. In terms of simplicity and probability of failure would be very very low and I’m filtering on the require validations.

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){
    require (balances[msg.sender] >= _value);
    uint balanceBefore = balances [msg.sender];
    balances [msg.sender].sub (_value);
    balances [_to].add (_value);
    assert (balances [msg.sender] == balanceBefore.sub(_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 && balances [_from] >= _value);
    uint balanceBefore = balances [_from];
    allowed [_from] [msg.sender].sub (_value);
    balances [_from].sub (_value);
    balances [_to].add (_value);
    assert (balances [_from] == balanceBefore.sub (_value));
    emit Transfer(_from, _to, _value);
    _success = true;
    
  }

}

Hey guys,

Here is my solution:

ERC-20 Assignment

pragma solidity 0.7.5;
import ā€˜./Safe_Math.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){
    // Does sender have enough funds
    require(balances[msg.sender] >= _value, ā€˜Not enough funds’);
    // If so, transfer
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    // fire Transfer event
    emit Transfer(msg.sender, _to, _value);
    //return successful transfer
    return _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) {
    //Does owner have enough funds
    require(balances[msg.sender] >= _value, ā€˜Not enough funds’);
    //if so, then spender allowed to withdraw value from owners account
    allowed[msg.sender][_spender] = _value;
    balances[msg.sender] = balances[msg.sender].sub(_value);
    //emit Approval event
    emit Approval(msg.sender, _spender, _value);
    //return successful spender withdrawal
    return _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){
    //does owner have enough tokens to transfer and can the specified amount be spent
    require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value, ā€˜not enough funds’);
    //remove spent amount
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
    //if funds available, proceed to transfer
    balances[_from] = balances[_from].sub(_value);
    balances[_to] = balances[_to].add(_value);
    //fire Transfer event
    emit Transfer(_from, _to, _value);
    //return successful transfer
    return _success = true;
    }

}

Please let me know what I could improve. Thanks :+1: :smile:

1 Like
function transfer(address payable _to, uint256 _value) public returns (bool _success){
    require(_value >= balances[msg.sender], "Insufficient balance"); 
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    emit Transfer(msg.sender,_to,_value);
    _success = true;
  }
function approve(address _spender, uint256 _value) public returns (bool _success) {
      allowed[msg.sender][_spender] = _value;
      emit Approval(msg.sender, _spender, _value);
      _success = true;
  }
function transferFrom(address _from, address _to, uint256 _value) public returns (bool _success){
      require(_value <= balances[_from]);
      require(_value <= allowed[_from][msg.sender]);
      balances[_from] -= _value;
      allowed[_from][msg.sender] -= _value;
      balances[_to] += _value;
      emit Transfer(_from,_to,_value);
      _success = true;
  }
1 Like
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(msg.sender != _to);
      require (balances[msg.sender] >= _value);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add (_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(balances[msg.sender] >= _value);
        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(msg.sender != _to);
      require (balances[msg.sender] >= _value);
       require ( allowed[_from][msg.sender] >= _value);
      balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add (_value);
    emit Transfer(_from,_to,_value);
     _success = true;
  }

}
1 Like
function transfer(address payable _to, uint256 _value) public returns (bool _success){
    require(balances[msg.sender] >= _value, "You don't have enough tokens to send");
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
    _success = true;
}

function approve(address _spender,uint256 _value) public returns (bool _success) {
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    _success = true;
}

function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
    require(allowed[_from][msg.sender] >= _value, "You are not approved to transfer this many tokens");
    require(balances[_from] >= _value, "You don't have enough tokens to send");
    balances[_from] -= _value;
    balances[_to] += _value;
    allowed[_from][msg.sender] -= 1;
    emit Transfer(_from, _to, _value);
    _success = true;
}
1 Like

In order to prevent overflow exploits I used the Safemath library. If you want to keep it very short this library can be implemented as follows:

pragma solidity 0.8.0;

library SafeMath { // Only relevant functions
	function sub(uint256 a, uint256 b) internal pure returns (uint256) {
	  assert(b <= a);
	  return a — b;
	}
	function add(uint256 a, uint256 b) internal pure returns (uint256)   {
	  uint256 c = a + b;
	  assert(c >= a);
	  return c;
	}
}

Only add and sub functions are necessary.

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){
      require(_value <= balances[msg.sender], "Insufficient token amount available!");
      require(_to != address(0), "Don't burn your precious tokens!");
      balances[msg.sender] = balances[msg.sender].sub(_value);
      balances[_to] = balances[_to].add(_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(_value <= balances[_from]);
    require(_value <= allowed[_from][msg.sender]);
    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);
    _success = true;
  }

}
1 Like

Here’s my solution:

// SPDX-License-Identifier: MIT

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){
    require(_value <= balances[msg.sender]);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_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(_value <= balances[_from]);
    require(_value <= allowed[_from][msg.sender]);
    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);
    _success = true;
  }

}```
1 Like

Hello All,

Here is what I came up with:

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);
     
     balances[msg.sender] -= _value;
     balances[_to] += _value;
     
     _success = true;
     emit Transfer(msg.sender, _to, _value);
    
  }

  /*
   * @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;
    _success = true;
    emit Approval(msg.sender, _spender, _value);
    
  }

  /*
   * @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);
    
    balances[_from] -= _value;
    balances[_to] += _value;
    _success = true;
    emit Transfer(_from, _to, _value);
    
    
  }

}
1 Like

My solution:

pragma solidity 0.8.6;

/**
 * @title ERC20 standard token implementation.
 * @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
 */
 // Initalization values:
 //   _NAME:     _SYMBOL: _DECIMALS:,
 // "TygerToken","TYGR",2,1000000000000000000
 //                           _INITIALOWNERBALANCE:
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,"Transfer value over balance.");
      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){
      require(allowed[_from][msg.sender] >= _value,"Request over allowance.");
      require(balances[_from] >= _value,"Third-party transfer value over balance.");
      balances[_from] -= _value;
      balances[_to] += _value;
      emit Transfer(_from, _to, _value);
      _success=true;
  }

}

Seen the next video: I haven’t decreased the allowance after third-party transfer… SHAME!

1 Like

Here’s my solution:

// "SPDX-License-Identifier: AGPL-3.0"
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 "./utils/Ownable.sol";
import "./utils/SafeMath.sol";

contract Token is Ownable{

  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){
    // Checks, Effects, Interactions
    require(balances[msg.sender] >= _value);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_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(balances[_from] >= _value);   // Check the value of the senders wallet
    require(allowed[_from][ msg.sender] >= _value);   // Check the allowance of the aloowed sender will be sufficient
    balances[_from] = balances[msg.sender].sub(_value);   // Alter the senders balance
    balances[_to] = balances[_to].add(_value);    // Alter the receivers balance
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);    // Alter the approval balance

    emit Transfer(_from, _to, _value);
    
    _success = true;
  }

}
1 Like