commit 27ea14772f023326963edf127a9d0c55d1d797b6
parent 4d72398adfaadfa2dd7f4bf1ad91ceea0d005c39
Author: nolash <dev@holbrook.no>
Date: Tue, 1 Dec 2020 23:54:17 +0100
Deploy script to package, dockerfile
Diffstat:
14 files changed, 306 insertions(+), 279 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,3 +0,0 @@
-* 0.0.1
- - Adapt Bancor ERC20 token contract
- - Add deploy-and-gift script
diff --git a/Dockerfile b/Dockerfile
@@ -0,0 +1,28 @@
+FROM ethereum/solc:0.6.12
+
+FROM python:3.8.6-alpine
+
+COPY --from=0 /usr/bin/solc /usr/bin/solc
+
+RUN apk update &&\
+ apk add gcc bash musl-dev
+
+WORKDIR /usr/src
+
+# Try to keep everything above here re-usable!
+
+COPY ./solidity/ /usr/src/giftable_erc20_token/solidity/
+COPY ./python/ /usr/src/giftable_erc20_token/python/
+
+RUN cd giftable_erc20_token/solidity && \
+ solc GiftableToken.sol --abi | awk 'NR>3' > GiftableToken.abi.json
+
+RUN cd giftable_erc20_token/solidity && \
+ solc GiftableToken.sol --bin | awk 'NR>3' > GiftableToken.bin && \
+ truncate -s "$((`stat -t -c "%s" GiftableToken.bin`-1))" GiftableToken.bin
+
+RUN cd giftable_erc20_token/python && \
+ pip install --extra-index-url https://pip.grassrootseconomics.net:8433 .
+
+# To deploy:
+# giftable-token-deploy --contracts-dir giftable_erc20_token/solidity/ <amount>
diff --git a/GiftableToken.sol b/GiftableToken.sol
@@ -1,160 +0,0 @@
-pragma solidity ^0.6.12;
-
-// SPDX-License-Identifier: SEE LICENSE IN LICENSE
-
-/*
- * 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;
- }
-}
diff --git a/LICENSE b/LICENSE
@@ -1,45 +0,0 @@
- 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.
diff --git a/deploy.py b/deploy.py
@@ -1,71 +0,0 @@
-"""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', action='append', type=str, help='Account to fund')
-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()
-
- 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.a != None:
- for a in args.a:
- 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)
diff --git a/python/CHANGELOG b/python/CHANGELOG
@@ -0,0 +1,5 @@
+* 0.0.2
+ - Move deploy script to package
+* 0.0.1
+ - Adapt Bancor ERC20 token contract
+ - Add deploy-and-gift script
diff --git a/VERSION b/python/VERSION
diff --git a/python/giftable_erc20_token/runnable/deploy.py b/python/giftable_erc20_token/runnable/deploy.py
@@ -0,0 +1,77 @@
+"""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 os
+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', action='append', type=str, help='Account to fund')
+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('amount', type=int, help='Initial token supply (will be owned by contract creator)')
+args = argparser.parse_args()
+
+if args.v:
+ logg.setLevel(logging.DEBUG)
+
+def main():
+ w3 = web3.Web3(web3.Web3.HTTPProvider(args.p))
+
+ f = open(os.path.join(args.contracts_dir, 'GiftableToken.abi.json'), 'r')
+ abi = json.load(f)
+ f.close()
+
+ f = open(os.path.join(args.contracts_dir, 'GiftableToken.bin'), 'r')
+ bytecode = f.read()
+ f.close()
+
+ 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.a != None:
+ for a in args.a:
+ 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)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/requirements.txt b/python/requirements.txt
diff --git a/python/setup.cfg b/python/setup.cfg
@@ -0,0 +1,32 @@
+[metadata]
+name = giftable-erc20-token
+version = 0.0.2
+description = Simple ERC20 contract with deployment script that lets any address mint and gift itself tokens.
+author = Louis Holbrook
+author_email = dev@holbrook.no
+url = https://gitlab.com/nolash/giftable-erc-token
+keywords =
+ ethereum
+classifiers =
+ Programming Language :: Python :: 3
+ Operating System :: OS Independent
+ Development Status :: 3 - Alpha
+ Environment :: No Input/Output (Daemon)
+ Intended Audience :: Developers
+ License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
+ Topic :: Internet
+ #Topic :: Blockchain :: EVM
+license = GPL3
+licence_files =
+ LICENSE
+
+[options]
+python_requires = >= 3.6
+packages =
+ giftable_erc20_token.runnable
+install_requires =
+ web3==5.12.2
+
+[options.entry_points]
+console_scripts =
+ giftable-token-deploy = giftable_erc20_token.runnable.deploy:main
diff --git a/python/setup.py b/python/setup.py
@@ -0,0 +1,4 @@
+from setuptools import setup
+
+setup(
+ )
diff --git a/GiftableToken.abi.json b/solidity/GiftableToken.abi.json
diff --git a/GiftableToken.bin b/solidity/GiftableToken.bin
diff --git a/solidity/GiftableToken.sol b/solidity/GiftableToken.sol
@@ -0,0 +1,160 @@
+pragma solidity ^0.6.12;
+
+// SPDX-License-Identifier: SEE LICENSE IN LICENSE
+
+/*
+ * 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) public {
+ // 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;
+ }
+}