mirror of
https://github.com/chaintool-py/eth-erc20.git
synced 2024-11-24 10:46:47 +01:00
Initial commit
This commit is contained in:
commit
f2d35bf3fd
3
CHANGELOG
Normal file
3
CHANGELOG
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* 0.0.1
|
||||||
|
- Adapt Bancor ERC20 token contract
|
||||||
|
- Add deploy-and-gift script
|
1
GiftableToken.abi.json
Normal file
1
GiftableToken.abi.json
Normal file
@ -0,0 +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"}]
|
1
GiftableToken.bin
Normal file
1
GiftableToken.bin
Normal file
File diff suppressed because one or more lines are too long
159
GiftableToken.sol
Normal file
159
GiftableToken.sol
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
45
LICENSE
Normal file
45
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.
|
74
deploy.py
Normal file
74
deploy.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
"""Deploys giftable token, and optionally gifts a set amount to all accounts in wallet
|
||||||
|
|
||||||
|
.. moduleauthor:: Louis Holbrook <dev@holbrook.no>
|
||||||
|
.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# standard imports
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# third-party imports
|
||||||
|
import web3
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
logg = logging.getLogger()
|
||||||
|
|
||||||
|
logging.getLogger('web3').setLevel(logging.WARNING)
|
||||||
|
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
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('-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('-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('-a', '--account', dest='a', type=str, help='Owner account. If not specified, first account in wallet will be used')
|
||||||
|
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)')
|
||||||
|
args = argparser.parse_args()
|
||||||
|
|
||||||
|
if args.v:
|
||||||
|
logg.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
w3 = web3.Web3(web3.Web3.HTTPProvider(args.p))
|
||||||
|
|
||||||
|
f = open('./GiftableToken.abi.json', 'r')
|
||||||
|
abi = json.load(f)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
f = open('./GiftableToken.bin', 'r')
|
||||||
|
bytecode = f.read()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if args.a != None:
|
||||||
|
a = web3.Web3.toChecksumAddress(args.a)
|
||||||
|
w3.eth.defaultAccount = a
|
||||||
|
else:
|
||||||
|
w3.eth.defaultAccount = w3.eth.accounts[0]
|
||||||
|
|
||||||
|
c = w3.eth.contract(abi=abi, bytecode=bytecode)
|
||||||
|
tx_hash = c.constructor(args.n, args.s, args.d, args.amount).transact()
|
||||||
|
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
||||||
|
address = rcpt.contractAddress
|
||||||
|
c = w3.eth.contract(abi=abi, address=address)
|
||||||
|
|
||||||
|
logg.debug('construct tx {} address {}'.format(tx_hash.hex(), address))
|
||||||
|
balance = c.functions.balanceOf(w3.eth.defaultAccount).call()
|
||||||
|
logg.info('balance {}: {}'.format(w3.eth.defaultAccount, balance))
|
||||||
|
|
||||||
|
if args.g:
|
||||||
|
for a in w3.eth.accounts:
|
||||||
|
if a == w3.eth.defaultAccount:
|
||||||
|
continue
|
||||||
|
tx_hash = c.functions.gift(a, args.amount).transact()
|
||||||
|
rcpt = w3.eth.getTransactionReceipt(tx_hash)
|
||||||
|
balance = c.functions.balanceOf(a).call()
|
||||||
|
logg.info('balance {}: {}'.format(a, balance))
|
||||||
|
|
||||||
|
print(address)
|
Loading…
Reference in New Issue
Block a user