Initial commit

This commit is contained in:
nolash 2020-11-17 19:23:57 +01:00
commit f2d35bf3fd
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 284 additions and 0 deletions

3
CHANGELOG Normal file
View File

@ -0,0 +1,3 @@
* 0.0.1
- Adapt Bancor ERC20 token contract
- Add deploy-and-gift script

1
GiftableToken.abi.json Normal file
View 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

File diff suppressed because one or more lines are too long

159
GiftableToken.sol Normal file
View 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
View 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.

1
VERSION Normal file
View File

@ -0,0 +1 @@
0.0.1

74
deploy.py Normal file
View 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)