mirror of
https://github.com/chaintool-py/eth-erc20.git
synced 2024-10-16 18:46:46 +02:00
160 lines
5.5 KiB
Solidity
160 lines
5.5 KiB
Solidity
|
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
|
||
|
pragma solidity ^0.7.4;
|
||
|
|
||
|
/*
|
||
|
* This is a MOCK token used for DEVELOPMENT PURPOSES ONLY.
|
||
|
* It allows anyone to freely mint tokens with themselves as beneficiaries
|
||
|
* Code is based on the ERC20Token contract from Bancor's contracts-solidity repository
|
||
|
*
|
||
|
* @dev ERC20 Standard Token implementation
|
||
|
*/
|
||
|
|
||
|
contract GiftableToken { //is IERC20Token, Utils {
|
||
|
//using SafeMath for uint256;
|
||
|
|
||
|
string public name;
|
||
|
string public symbol;
|
||
|
uint8 public decimals;
|
||
|
uint256 public totalSupply;
|
||
|
mapping (address => uint256) public balanceOf;
|
||
|
mapping (address => mapping (address => uint256)) public allowance;
|
||
|
|
||
|
/**
|
||
|
* @dev triggered when tokens are transferred between wallets
|
||
|
*
|
||
|
* @param _from source address
|
||
|
* @param _to target address
|
||
|
* @param _value transfer amount
|
||
|
*/
|
||
|
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||
|
|
||
|
/**
|
||
|
* @dev triggered when a wallet allows another wallet to transfer tokens from on its behalf
|
||
|
*
|
||
|
* @param _owner wallet that approves the allowance
|
||
|
* @param _spender wallet that receives the allowance
|
||
|
* @param _value allowance amount
|
||
|
*/
|
||
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||
|
|
||
|
event ChangedSupply(uint256 _oldTotal, uint256 _newTotal);
|
||
|
|
||
|
/**
|
||
|
* @dev initializes a new ERC20Token instance
|
||
|
*
|
||
|
* @param _name token name
|
||
|
* @param _symbol token symbol
|
||
|
* @param _decimals decimal points, for display purposes
|
||
|
* @param _initialSupply total supply of token units
|
||
|
*/
|
||
|
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _initialSupply) {
|
||
|
// validate input
|
||
|
require(bytes(_name).length > 0, "ERR_INVALID_NAME");
|
||
|
require(bytes(_symbol).length > 0, "ERR_INVALID_SYMBOL");
|
||
|
|
||
|
name = _name;
|
||
|
symbol = _symbol;
|
||
|
decimals = _decimals;
|
||
|
totalSupply = _initialSupply;
|
||
|
balanceOf[msg.sender] = _initialSupply;
|
||
|
}
|
||
|
|
||
|
// validates an address - currently only checks that it isn't null
|
||
|
modifier validAddress(address _address) {
|
||
|
_validAddress(_address);
|
||
|
_;
|
||
|
}
|
||
|
|
||
|
// error message binary size optimization
|
||
|
function _validAddress(address _address) internal pure {
|
||
|
require(_address != address(0), "ERR_INVALID_ADDRESS");
|
||
|
}
|
||
|
|
||
|
|
||
|
function gift(address _to, uint256 _value)
|
||
|
public
|
||
|
virtual
|
||
|
validAddress(_to)
|
||
|
returns (bool)
|
||
|
{
|
||
|
totalSupply = totalSupply + _value;
|
||
|
uint256 oldSupply = balanceOf[_to];
|
||
|
balanceOf[_to] = balanceOf[_to] + _value;
|
||
|
emit ChangedSupply(oldSupply, balanceOf[_to]);
|
||
|
emit Transfer(address(0x00), _to, _value);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dev transfers tokens to a given address
|
||
|
* throws on any error rather then return a false flag to minimize user errors
|
||
|
*
|
||
|
* @param _to target address
|
||
|
* @param _value transfer amount
|
||
|
*
|
||
|
* @return true if the transfer was successful, false if it wasn't
|
||
|
*/
|
||
|
function transfer(address _to, uint256 _value)
|
||
|
public
|
||
|
virtual
|
||
|
validAddress(_to)
|
||
|
returns (bool)
|
||
|
{
|
||
|
balanceOf[msg.sender] = balanceOf[msg.sender] - _value;
|
||
|
balanceOf[_to] = balanceOf[_to] + _value;
|
||
|
emit Transfer(msg.sender, _to, _value);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dev transfers tokens to a given address on behalf of another address
|
||
|
* throws on any error rather then return a false flag to minimize user errors
|
||
|
*
|
||
|
* @param _from source address
|
||
|
* @param _to target address
|
||
|
* @param _value transfer amount
|
||
|
*
|
||
|
* @return true if the transfer was successful, false if it wasn't
|
||
|
*/
|
||
|
function transferFrom(address _from, address _to, uint256 _value)
|
||
|
public
|
||
|
virtual
|
||
|
validAddress(_from)
|
||
|
validAddress(_to)
|
||
|
returns (bool)
|
||
|
{
|
||
|
allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value;
|
||
|
balanceOf[_from] = balanceOf[_from] - _value;
|
||
|
balanceOf[_to] = balanceOf[_to] + _value;
|
||
|
emit Transfer(_from, _to, _value);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dev allows another account/contract to transfers tokens on behalf of the caller
|
||
|
* throws on any error rather then return a false flag to minimize user errors
|
||
|
*
|
||
|
* also, to minimize the risk of the approve/transferFrom attack vector
|
||
|
* (see https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/), approve has to be called twice
|
||
|
* in 2 separate transactions - once to change the allowance to 0 and secondly to change it to the new allowance value
|
||
|
*
|
||
|
* @param _spender approved address
|
||
|
* @param _value allowance amount
|
||
|
*
|
||
|
* @return true if the approval was successful, false if it wasn't
|
||
|
*/
|
||
|
function approve(address _spender, uint256 _value)
|
||
|
public
|
||
|
virtual
|
||
|
validAddress(_spender)
|
||
|
returns (bool)
|
||
|
{
|
||
|
// if the allowance isn't 0, it can only be updated to 0 to prevent an allowance change immediately after withdrawal
|
||
|
require(_value == 0 || allowance[msg.sender][_spender] == 0, "ERR_INVALID_AMOUNT");
|
||
|
|
||
|
allowance[msg.sender][_spender] = _value;
|
||
|
emit Approval(msg.sender, _spender, _value);
|
||
|
return true;
|
||
|
}
|
||
|
}
|