mirror of
https://github.com/chaintool-py/eth-erc20.git
synced 2024-11-22 01:36:46 +01:00
Rewrite contract, new license, adds settable minters
This commit is contained in:
parent
27ea14772f
commit
30baee6d19
45
python/LICENSE
Normal file
45
python/LICENSE
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
Bprotocol Foundation (Bancor) LICENSE
|
||||||
|
|
||||||
|
1. SUBJECT TO THE PROVISIONS SET FORTH HEREIN, INCLUDING “EFFECTIVE DATE”, YOU CAN
|
||||||
|
USE THIS CODE, FILE AND/OR SOFTWARE (“SOFTWARE”) ONLY IN CONNECTION WITH THE
|
||||||
|
BANCOR LIQUIDITY NETWORK AND/OR THE USE OF BNT ("PERMITTED USE"). ANY OTHER USE IS
|
||||||
|
PROHIBITED UNLESS THE USER SHALL RECEIVE AN EXPLICIT PRIOR WRITTEN APPROVAL FROM
|
||||||
|
BPROTOCOL FOUNDATION (BANCOR) TO DO SO (PLEASE CONTACT license@bancor.network IN
|
||||||
|
THIS REGARD), WHICH APPROVAL, IF GIVEN, MAY REQUIRE THE OBTAINMENT OF SEPARATE
|
||||||
|
LICENSE UNDER A DIFFERENT LICENSING MODEL. USING THIS SOFTWARE NOT IN THE FRAME OF
|
||||||
|
SUCH PERMITTED USE MAY, AMONG OTHERS, ALSO BREACH PATENT RIGHTS CONCERNING PATENTS
|
||||||
|
WHICH ARE EMBODIED/INCORPORATED/USED IN THIS SOFTWARE.
|
||||||
|
|
||||||
|
2. ANY SUCH PERMITTED USE SHOULD ALSO COMPLY WITH THE TERMS BELOW.
|
||||||
|
|
||||||
|
3. Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
A. Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
B. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
C. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
EFFECTIVE DATE: THIS LICENSE SHALL APPLY ONLY TO SOFTWARE (OR ANY VERSION THEREOF),
|
||||||
|
THAT HAS BEEN PUBLISHED AFTER THE DATE AND TIME THIS LICENSE HAS BEEN FIRST PUBLISHED
|
||||||
|
(“EFFECTIVE DATE”); Any previous versions published prior to the effective date (“Older Versions”)
|
||||||
|
shall remain licensed under the Apache License, Version 2.0 (the "Older Versions License");
|
||||||
|
You may obtain a copy of the Older Version License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
you may not use this file except in compliance with the Older Version License. Unless
|
||||||
|
required by applicable law or agreed to in writing, Older Versions distributed under the
|
||||||
|
Older Version License are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||||
|
OF ANY KIND, either express or implied. See the Older Version License for the specific
|
||||||
|
language governing permissions and limitations under the Older Version License.
|
@ -24,11 +24,11 @@ logging.getLogger('urllib3').setLevel(logging.WARNING)
|
|||||||
|
|
||||||
argparser = argparse.ArgumentParser()
|
argparser = argparse.ArgumentParser()
|
||||||
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)')
|
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)')
|
||||||
#argparser.add_argument('-g', '--gift', dest='g', action='store_true', help='If set, tokens will be gifted to all accounts in provider wallet')
|
|
||||||
argparser.add_argument('-n', '--name', dest='n', default='Giftable Token', type=str, help='Token name')
|
argparser.add_argument('-n', '--name', dest='n', default='Giftable Token', type=str, help='Token name')
|
||||||
argparser.add_argument('-s', '--symbol', dest='s', default='GFT', type=str, help='Token symbol')
|
argparser.add_argument('-s', '--symbol', dest='s', default='GFT', type=str, help='Token symbol')
|
||||||
argparser.add_argument('-d', '--decimals', dest='d', default=18, type=int, help='Token decimals')
|
argparser.add_argument('-d', '--decimals', dest='d', default=18, type=int, help='Token decimals')
|
||||||
argparser.add_argument('-a', '--account', dest='a', action='append', type=str, help='Account to fund')
|
argparser.add_argument('-a', '--account', dest='a', action='append', type=str, help='Account to fund')
|
||||||
|
argparser.add_argument('-m', '--minter', dest='m', action='append', type=str, help='Minter to add')
|
||||||
argparser.add_argument('--contracts-dir', dest='contracts_dir', type=str, default='.', help='Directory containing bytecode and abi')
|
argparser.add_argument('--contracts-dir', dest='contracts_dir', type=str, default='.', help='Directory containing bytecode and abi')
|
||||||
argparser.add_argument('-v', action='store_true', help='Be verbose')
|
argparser.add_argument('-v', action='store_true', help='Be verbose')
|
||||||
argparser.add_argument('amount', type=int, help='Initial token supply (will be owned by contract creator)')
|
argparser.add_argument('amount', type=int, help='Initial token supply (will be owned by contract creator)')
|
||||||
@ -51,25 +51,34 @@ def main():
|
|||||||
w3.eth.defaultAccount = w3.eth.accounts[0]
|
w3.eth.defaultAccount = w3.eth.accounts[0]
|
||||||
|
|
||||||
c = w3.eth.contract(abi=abi, bytecode=bytecode)
|
c = w3.eth.contract(abi=abi, bytecode=bytecode)
|
||||||
tx_hash = c.constructor(args.n, args.s, args.d, args.amount).transact()
|
tx_hash = c.constructor(args.n, args.s, args.d).transact()
|
||||||
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
||||||
address = rcpt.contractAddress
|
address = rcpt.contractAddress
|
||||||
c = w3.eth.contract(abi=abi, address=address)
|
c = w3.eth.contract(abi=abi, address=address)
|
||||||
|
|
||||||
logg.debug('construct tx {} address {}'.format(tx_hash.hex(), address))
|
logg.debug('construct tx {} address {}'.format(tx_hash.hex(), address))
|
||||||
|
|
||||||
balance = c.functions.balanceOf(w3.eth.defaultAccount).call()
|
balance = c.functions.balanceOf(w3.eth.defaultAccount).call()
|
||||||
logg.info('balance {}: {}'.format(w3.eth.defaultAccount, balance))
|
logg.info('balance {}: {} {}'.format(w3.eth.defaultAccount, balance, tx_hash))
|
||||||
|
|
||||||
|
|
||||||
if args.a != None:
|
if args.a != None:
|
||||||
for a in args.a:
|
for a in args.a:
|
||||||
if a == w3.eth.defaultAccount:
|
if a == w3.eth.defaultAccount:
|
||||||
continue
|
continue
|
||||||
tx_hash = c.functions.gift(a, args.amount).transact()
|
tx_hash_mint = c.functions.mint(args.amount).transact()
|
||||||
|
tx_hash_transfer = c.functions.transfer(a, args.amount).transact()
|
||||||
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
||||||
balance = c.functions.balanceOf(a).call()
|
balance = c.functions.balanceOf(a).call()
|
||||||
logg.info('balance {}: {}'.format(a, balance))
|
logg.info('balance {}: {}'.format(a, balance))
|
||||||
|
|
||||||
|
if args.m != None:
|
||||||
|
for a in args.m:
|
||||||
|
if a == w3.eth.defaultAccount:
|
||||||
|
continue
|
||||||
|
tx_hash_minter = c.functions.addMinter(a).transact()
|
||||||
|
logg.info('minter {}'.format(a))
|
||||||
|
|
||||||
print(address)
|
print(address)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"uint256","name":"_initialSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldTotal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTotal","type":"uint256"}],"name":"ChangedSupply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"gift","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
|
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferFrom","type":"event"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"addMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"removeMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,160 +1,74 @@
|
|||||||
pragma solidity ^0.6.12;
|
pragma solidity >=0.6.12;
|
||||||
|
|
||||||
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/*
|
contract GiftableToken {
|
||||||
* This is a MOCK token used for DEVELOPMENT PURPOSES ONLY.
|
|
||||||
* It allows anyone to freely mint tokens with themselves as beneficiaries
|
address owner;
|
||||||
* Code is based on the ERC20Token contract from Bancor's contracts-solidity repository
|
mapping(address => bool) minters;
|
||||||
*
|
|
||||||
* @dev ERC20 Standard Token implementation
|
string public name;
|
||||||
*/
|
string public symbol;
|
||||||
|
uint8 public decimals;
|
||||||
contract GiftableToken { //is IERC20Token, Utils {
|
uint256 public totalSupply;
|
||||||
//using SafeMath for uint256;
|
mapping (address => uint256) public balanceOf;
|
||||||
|
mapping (address => mapping (address => uint256)) public allowances;
|
||||||
string public name;
|
|
||||||
string public symbol;
|
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||||
uint8 public decimals;
|
event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value);
|
||||||
uint256 public totalSupply;
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||||
mapping (address => uint256) public balanceOf;
|
|
||||||
mapping (address => mapping (address => uint256)) public allowance;
|
constructor(string memory _name, string memory _symbol, uint8 _decimals) {
|
||||||
|
owner = msg.sender;
|
||||||
/**
|
name = _name;
|
||||||
* @dev triggered when tokens are transferred between wallets
|
symbol = _symbol;
|
||||||
*
|
decimals = _decimals;
|
||||||
* @param _from source address
|
minters[msg.sender] = true;
|
||||||
* @param _to target address
|
}
|
||||||
* @param _value transfer amount
|
|
||||||
*/
|
function mint(uint256 _value) public returns (bool) {
|
||||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
require(minters[msg.sender]);
|
||||||
|
|
||||||
/**
|
balanceOf[msg.sender] += _value;
|
||||||
* @dev triggered when a wallet allows another wallet to transfer tokens from on its behalf
|
totalSupply += _value;
|
||||||
*
|
|
||||||
* @param _owner wallet that approves the allowance
|
return true;
|
||||||
* @param _spender wallet that receives the allowance
|
}
|
||||||
* @param _value allowance amount
|
|
||||||
*/
|
function addMinter(address _minter) public returns (bool) {
|
||||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
require(msg.sender == owner);
|
||||||
|
|
||||||
event ChangedSupply(uint256 _oldTotal, uint256 _newTotal);
|
minters[_minter] = true;
|
||||||
|
|
||||||
/**
|
return true;
|
||||||
* @dev initializes a new ERC20Token instance
|
}
|
||||||
*
|
|
||||||
* @param _name token name
|
function removeMinter(address _minter) public returns (bool) {
|
||||||
* @param _symbol token symbol
|
require(msg.sender == owner || msg.sender == _minter);
|
||||||
* @param _decimals decimal points, for display purposes
|
|
||||||
* @param _initialSupply total supply of token units
|
minters[_minter] = false;
|
||||||
*/
|
|
||||||
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _initialSupply) public {
|
return true;
|
||||||
// validate input
|
}
|
||||||
require(bytes(_name).length > 0, "ERR_INVALID_NAME");
|
|
||||||
require(bytes(_symbol).length > 0, "ERR_INVALID_SYMBOL");
|
function transfer(address _to, uint256 _value) public returns (bool) {
|
||||||
|
balanceOf[msg.sender] -= _value;
|
||||||
name = _name;
|
balanceOf[_to] += _value;
|
||||||
symbol = _symbol;
|
emit Transfer(msg.sender, _to, _value);
|
||||||
decimals = _decimals;
|
return true;
|
||||||
totalSupply = _initialSupply;
|
}
|
||||||
balanceOf[msg.sender] = _initialSupply;
|
|
||||||
}
|
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
||||||
|
allowances[_from][msg.sender] = allowances[_from][msg.sender] - _value;
|
||||||
// validates an address - currently only checks that it isn't null
|
balanceOf[_from] -= _value;
|
||||||
modifier validAddress(address _address) {
|
balanceOf[_to] += _value;
|
||||||
_validAddress(_address);
|
emit TransferFrom(_from, _to, msg.sender, _value);
|
||||||
_;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// error message binary size optimization
|
function approve(address _spender, uint256 _value) public returns (bool) {
|
||||||
function _validAddress(address _address) internal pure {
|
allowances[msg.sender][_spender] += _value;
|
||||||
require(_address != address(0), "ERR_INVALID_ADDRESS");
|
emit Approval(msg.sender, _spender, _value);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user