def test_testrpc_chain_has_registrar(project_dir): project = Project() with project.get_chain('testrpc') as chain: assert chain.has_registrar is True
def main(chain, address, csv_file): """Extract crowdsale invested events. This is useful for RelaunchCrowdsale to rebuild the data. """ project = Project() timestamp_filename = "block-timestamps.json" with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) # Sanity check print("Block number is", web3.eth.blockNumber) Crowdsale = c.provider.get_base_contract_factory( 'MintedTokenCappedCrowdsale') crowdsale = Crowdsale(address=address) Token = c.provider.get_base_contract_factory('CrowdsaleToken') token = Token(address=crowdsale.functions.token().call()) decimals = token.functions.decimals().call() decimal_multiplier = 10**decimals print("We have", decimals, "decimals, multiplier is", decimal_multiplier) print("Total amount raised is", from_wei(crowdsale.functions.weiRaised().call(), "ether"), "ether") print("Getting events") events = crowdsale.events.Invested().createFilter( fromBlock=0).get_all_entries() print("Writing results to", csv_file) # Block number -> timestamp mappings timestamps = {} # Load cached timestamps if os.path.exists(timestamp_filename): with open(timestamp_filename, "rt") as inp: timestamps = json.load(inp) with open(csv_file, 'w', newline='') as out: writer = csv.writer(out) writer.writerow([ "Address", "Payment at", "Tx hash", "Tx index", "Invested ETH", "Received tokens" ]) for idx, e in enumerate(events): if idx % 100 == 0: print("Writing event", idx) # Save cached timestamps with open(timestamp_filename, "wt") as out: json.dump(timestamps, out) block_number = e["blockNumber"] if block_number not in timestamps: timestamps[block_number] = web3.eth.getBlock( block_number)["timestamp"] amount = Decimal( e["args"]["tokenAmount"]) / Decimal(decimal_multiplier) tokens = amount * decimal_multiplier # http://stackoverflow.com/a/19965088/315168 if not tokens % 1 == 0: raise RuntimeError( "Could not convert token amount to decimal format. It was not an integer after restoring non-fractional balance: {} {} {}" .format(tokens, amount, decimal_multiplier)) timestamp = timestamps[block_number] dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) writer.writerow([ e["args"]["investor"], dt.isoformat(), e["transactionHash"], e["transactionIndex"], from_wei(e["args"]["weiAmount"], "ether"), amount, ]) print("Total", len(events), "invest events") print("All done! Enjoy your decentralized future.")
def main(**kwargs): project = Project() chain_name = kwargs['chain'] owner = kwargs['owner'] challenge_period = kwargs['challenge_period'] supply = kwargs['supply'] token_name = kwargs['token_name'] token_decimals = kwargs['token_decimals'] token_symbol = kwargs['token_symbol'] token_address = kwargs['token_address'] output_json = kwargs['output_json'] delta_settle = kwargs['delta_settle'] delta_withdraw = kwargs['delta_withdraw'] supply *= 10**(token_decimals) txn_wait = 250 #assert challenge_period >= 500, 'Challenge period should be >= 500 blocks' # PART OF TEMP FIX TO ISSUE 414 IN PULL REQUEST: https://github.com/raiden-network/microraiden/pull/416 # if chain_name == 'rinkeby': # txn_wait = 500 # end print( '''Make sure {} chain is running, you can connect to it and it is synced, or you'll get timeout'''.format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 print('Web3 provider is', web3.providers[0]) # Temporary fix for Rinkeby; PoA adds bytes to extraData, which is not yellow-paper-compliant # https://github.com/ethereum/web3.py/issues/549 if int(web3.version.network) == 4: txn_wait = 500 size_extraData_for_poa = 200 pythonic_middleware.__closure__[2].cell_contents[ 'eth_getBlockByNumber'].args[1].args[0][ 'extraData'] = to_hexbytes(size_extraData_for_poa, variable_length=True) pythonic_middleware.__closure__[2].cell_contents[ 'eth_getBlockByHash'].args[1].args[0][ 'extraData'] = to_hexbytes(size_extraData_for_poa, variable_length=True) # end owner = web3.eth.accounts[0] assert owner and is_address(owner), 'Invalid owner provided.' owner = to_checksum_address(owner) print('Owner is', owner) assert web3.eth.getBalance( owner) > 0, 'Account with insuficient funds.' token = chain.provider.get_contract_factory('CustomToken') if not token_address: print("Trying to deploy token.") txhash = token.deploy( args=[supply, token_name, token_symbol, token_decimals], transaction={'from': owner}) receipt = check_succesful_tx(chain.web3, txhash, txn_wait) token_address = receipt['contractAddress'] assert token_address and is_address(token_address) token_address = to_checksum_address(token_address) print(token_name, 'address is', token_address) print(token_name, 'tx is', encode_hex(txhash)) print('Giving address %s some tokens.' % web3.eth.accounts[1]) txid = token.transact({ 'from': web3.eth.accounts[1], 'value': web3.toWei(100, 'finney'), 'to': token_address }).mint() print('Minting transaction: %s' % txid) receipt = check_succesful_tx(web3, txid, txn_wait) print('Minting transaction finished') microraiden_contract = chain.provider.get_contract_factory( 'RaidenMicroTransferChannels') txhash = microraiden_contract.deploy( args=[token_address, challenge_period, []], transaction={'from': owner}) receipt = check_succesful_tx(chain.web3, txhash, txn_wait) microraiden_address = receipt['contractAddress'] print('RaidenMicroTransferChannels txid is', encode_hex(txhash)) print('RaidenMicroTransferChannels address is', microraiden_address) owner = web3.eth.accounts[1] assert owner and is_address(owner), 'Invalid owner provided.' owner = to_checksum_address(owner) print('Owner is', owner) assert web3.eth.getBalance( owner) > 0, 'Account with insuficient funds.' guardian_contract = chain.provider.get_contract_factory( 'StateGuardian') txhash = guardian_contract.deploy(args=[delta_withdraw, delta_settle], transaction={ 'from': owner, 'value': 10000 }) receipt = check_succesful_tx(chain.web3, txhash, txn_wait) guardian_address = receipt['contractAddress'] print('StateGuardian tx is', encode_hex(txhash)) print('StateGuardian address is', guardian_address) if output_json: d = json.load(open(output_json)) d['token'] = token_address d['manager'] = microraiden_address d['monitor'] = guardian_address json.dump(d, open(output_json, 'w'))
def main(chain, address, csv_file): """Extract crowdsale contract investors.""" project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.providers[0]) # Sanity check print("Block number is", web3.eth.blockNumber) Crowdsale = c.provider.get_contract_factory( 'MintedTokenCappedCrowdsale') crowdsale = Crowdsale(address=address) print("Total amount raised is", from_wei(crowdsale.functions.weiRaised().call(), "ether"), "ether") print("Getting events") events = crowdsale.events.Invested().createFilter( fromBlock=0).get_all_entries() # Merge several transactions from the same address to one print("Analysing", len(events), "raw events") address_data = OrderedDict() for e in events: address = e["args"]["investor"] data = address_data.get(address, {}) # TODO: Not sure if we get events in block order timestamp = web3.eth.getBlock(e["blockNumber"])["timestamp"] current_first = data.get("first_payment", 99999999999999999) if timestamp < current_first: data["first_payment"] = timestamp data["raised"] = data.get("raised", 0) + from_wei( e["args"]["weiAmount"], "ether") data["tokens"] = data.get("tokens", 0) + e["args"]["tokenAmount"] address_data[address] = data if csv_file: print("Writing results to", csv_file) with open(csv_file, 'w', newline='') as out: writer = csv.writer(out) writer.writerow([ "Address", "First payment at", "Invested ETH", "Received tokens" ]) for address, data in address_data.items(): timestamp = data["first_payment"] dt = datetime.datetime.fromtimestamp( timestamp, tz=datetime.timezone.utc) writer.writerow([ address, dt.isoformat(), str(data["raised"]), str(data["tokens"]) ]) else: for address, data in address_data.items(): timestamp = data["first_payment"] dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) print(address, dt.isoformat(), str(data["raised"]), str(data["tokens"])) print("Total", len(address_data), "investors") print("All done! Enjoy your decentralized future.")
def main(chain, owner_address, token, csv_file, address_column, label_column, gas_price): """Reclaim tokens that failed AML check. Before the token release, after AML/post sale KYC data has been assembled, go through the addresses that failed the checks and get back tokens from those buyers. Owner account must have balance to perform the the reclaim transactions. Example: aml-reclaim \ --token=0x... \ --owner-address=0x... \ --address-column="address" \ --label-column="label" \ --csv-file=test.csv """ setup_console_logging() logger = logging.getLogger(__name__) project = Project() with project.get_chain(chain) as c: web3 = c.web3 logger.info("Web3 provider is %s", web3.providers[0]) logger.info("Owner account address is %s", owner_address) logger.info("Owner account balance is %s ETH", from_wei(web3.eth.getBalance(owner_address), "ether")) # Goes through geth account unlock process if needed if is_account_locked(web3, owner_address): request_account_unlock(c, owner_address, timeout=3600 * 6) assert not is_account_locked(web3, owner_address) Token = c.provider.get_base_contract_factory('AMLToken') token = Token(address=token) logger.info("Token address is %s", token.address) decimals = token.functions.decimals().call() logger.info("Total supply is %s", token.functions.totalSupply().call() / (10**decimals)) logger.info( "Owner account token balance is %s", token.functions.balanceOf(owner_address).call() / (10**decimals)) if gas_price: gas_price = int(gas_price) * 10**9 else: # Use default gas price with little multiplies to cut us at the front of the queue gas_price = web3.eth.gasPrice * 1.2 tx_params = { "from": owner_address, "gasPrice": gas_price, } logger.info("Using gas price of %f GWei", gas_price / 10**9) logger.info("Reading data from %s", csv_file) with open(csv_file, "rt") as inp: rows = prepare_csv(inp, address_column, label_column) logger.info("Total %s rows", len(rows)) amount = count_tokens_to_reclaim(token, rows) / 10**decimals logger.info("Claiming total %f tokens", amount) start_balance = from_wei(web3.eth.getBalance(owner_address), "ether") reclaim_all(token, rows, tx_params) end_balance = from_wei(web3.eth.getBalance(owner_address), "ether") logger.info("Deployment cost is %f ETH", start_balance - end_balance) logger.info("All done! Enjoy your decentralized future.")
def deploy(chain_name, authority_address, indexed_ordered_set_lib_address, sem_version_lib_address, package_db_address, release_db_address, release_validator_address, package_index_address): """ #. Deploy WhitelistAuthority #. Deploy Libraries: - EnumerableMappingLib - SemVersionLib - IndexedOrderedSetLib #. Deploy PackageDB - set Authority #. Deploy ReleaseDB - set Authority #. Deploy ReleaseValidator #. Deploy PackageIndex - set PackageDB - set Authority #. Setup Authorizations - PackageIndex -> PackageDB.setPackage(...) - PackageIndex -> PackageDB.setPackageOwner(...) - PackageIndex -> ReleaseDB.setRelease(...) - * -> ReleaseDB.setVersion(...) - * -> ReleaseDB.updateLatestTree(...) - * -> PackageIndex.release(...) - * -> PackageIndex.transferPackageOwner(...) """ project = Project() click.echo("Starting {0} chain... ".format(chain_name), nl=False) with project.get_chain(chain_name) as chain: click.echo("STARTED") web3 = chain.web3 click.echo( "Waiting for account {} to be unlocked... ".format( web3.eth.coinbase), nl=False, ) chain.wait.for_unlock(web3.eth.coinbase, timeout=600) click.echo("UNLOCKED") if authority_address: authority = chain.contract_factories.WhitelistAuthority( address=authority_address) else: authority = deploy_contract(chain, 'WhitelistAuthority') if release_validator_address: release_validator = chain.contract_factories.ReleaseValidator( address=release_validator_address) else: release_validator = deploy_contract(chain, 'ReleaseValidator') if sem_version_lib_address: sem_version_lib = chain.contract_factories.SemVersionLib( address=sem_version_lib_address, ) else: sem_version_lib = deploy_contract(chain, 'SemVersionLib') if indexed_ordered_set_lib_address: indexed_ordered_set_lib = chain.contract_factories.IndexedOrderedSetLib( address=indexed_ordered_set_lib_address, ) else: indexed_ordered_set_lib = deploy_contract(chain, 'IndexedOrderedSetLib') link_dependencies = { 'SemVersionLib': sem_version_lib.address, 'IndexedOrderedSetLib': indexed_ordered_set_lib.address, } if package_db_address: package_db = chain.contract_factories.PackageDB( address=package_db_address, ) else: package_db = deploy_contract(chain, 'PackageDB', link_dependencies=link_dependencies) if release_db_address: release_db = chain.contract_factories.ReleaseDB( address=release_db_address, ) else: release_db = deploy_contract(chain, 'ReleaseDB', link_dependencies=link_dependencies) if package_index_address: package_index = chain.contract_factories.PackageIndex( address=package_index_address) else: package_index = deploy_contract(chain, 'PackageIndex') click.echo("Beginning permission setup.") set_package_db_address_on_package_index(chain, package_index, package_db) set_release_db_address_on_package_index(chain, package_index, release_db) set_release_validator_address_on_package_index(chain, package_index, release_validator) set_authority(chain, authority, package_db) set_authority(chain, authority, release_db) set_authority(chain, authority, package_index) # Release DB set_can_call( chain=chain, authority=authority, caller_address=package_index.address, code_address=release_db.address, can_call=True, function_signature="setRelease(bytes32,bytes32,string)", ) set_anyone_can_call( chain=chain, authority=authority, code_address=release_db.address, can_call=True, function_signature="setVersion(uint32,uint32,uint32,string,string)", ) set_anyone_can_call( chain=chain, authority=authority, code_address=release_db.address, can_call=True, function_signature="updateLatestTree(bytes32)", ) # Package DB set_can_call( chain=chain, authority=authority, caller_address=package_index.address, code_address=package_db.address, can_call=True, function_signature="setPackage(string)", ) set_can_call( chain=chain, authority=authority, caller_address=package_index.address, code_address=package_db.address, can_call=True, function_signature="setPackageOwner(bytes32,address)", ) # Package Index set_anyone_can_call( chain=chain, authority=authority, code_address=package_index.address, can_call=True, function_signature= "release(string,uint32,uint32,uint32,string,string,string)", ) set_anyone_can_call( chain=chain, authority=authority, code_address=package_index.address, can_call=True, function_signature="transferPackageOwner(string,address)", ) click.echo("Finished permission setup.")
def main(chain, address, contract_address, csv_file, limit, start_from, multiplier): """Rebuild data on relaunched CrowdsaleToken contract. This allows you rerun investment data to fix potential errors in the contract. Example:: rebuild-crowdsale --address=0x001FC7d7E506866aEAB82C11dA515E9DD6D02c25 --chain=kovan --contract-address=0xf09e4a27a02afd29590a989cb2dda9af8eebc77f --start-from=0 --limit=600 --multiplier=12 --csv-file=inputdata.csv rebuild-crowdsale --address=0x001FC7d7E506866aEAB82C11dA515E9DD6D02c25 --chain=kovan --contract-address=0xf09e4a27a02afd29590a989cb2dda9af8eebc77f --start-from=0 --limit=600 --multiplier=12 --csv-file=inputdata.csv """ project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) print("Owner address is", address) print("Owner balance is", from_wei(web3.eth.getBalance(address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, address): request_account_unlock(c, address, timeout=3600*6) print("Reading data", csv_file) with open(csv_file, "rt") as inp: reader = csv.DictReader(inp) rows = [row for row in reader] print("Source data has", len(rows), "rows") print("Importing rows", start_from, "-", start_from + limit) RelaunchedCrowdsale = c.provider.get_base_contract_factory('RelaunchedCrowdsale') relaunched_crowdsale = RelaunchedCrowdsale(address=contract_address) print("Crowdsale contract is", contract_address) print("Currently issued", relaunched_crowdsale.call().tokensSold()) assert relaunched_crowdsale.call().owner().lower() == address.lower(), "We are not the crowdsale owner. Real owner is {}, we are {}".format(relaunched_crowdsale.call().owner(), address) multiplier = 10**multiplier start_time = time.time() start_balance = from_wei(web3.eth.getBalance(address), "ether") tx_to_confirm = [] # List of txids to confirm tx_batch_size = 16 # How many transactions confirm once cap_check = True for i in range(start_from, min(start_from+limit, len(rows))): data = rows[i] addr = data["Address"] wei = to_wei(data["Invested ETH"], "ether") fractional_tokens = Decimal(data["Received tokens"]) orig_txid = int(data["Tx hash"], 16) # orig_tx_index = int(data["Tx index"]) tokens = fractional_tokens * multiplier transaction = { "from": address, "gasPrice": int(web3.eth.gasPrice * 1.2) } # 40 GWei should be the low if transaction["gasPrice"] < 35 * 10**9: print("Got lowish gas price: {}".format(transaction)) transaction["gasPrice"] = 35 * 10**9 # http://stackoverflow.com/a/19965088/315168 if not tokens % 1 == 0: raise RuntimeError("Could not issue tokens because after multiplication was not integer: {} {} {}".format(tokens, fractional_tokens, multiplier)) end_balance = from_wei(web3.eth.getBalance(address), "ether") spent = start_balance - end_balance print("Row", i, "giving", tokens, "to", addr, "from tx", orig_txid, "ETH spent", spent, "time passed", time.time() - start_time) if relaunched_crowdsale.call().getRestoredTransactionStatus(orig_txid): print("Already restored, skipping") continue tokens = int(tokens) if cap_check: # See if our cap calculation is screwed if relaunched_crowdsale.call().isBreakingCap(wei, tokens, relaunched_crowdsale.call().weiRaised(), relaunched_crowdsale.call().tokensSold()): raise RuntimeError("Cap error") txid = relaunched_crowdsale.transact(transaction).setInvestorDataAndIssueNewToken(addr, wei, tokens, orig_txid) tx_to_confirm.append(txid) # Confirm N transactions when batch max size is reached if len(tx_to_confirm) >= tx_batch_size: check_multiple_succesful_txs(web3, tx_to_confirm) tx_to_confirm = [] # Confirm dangling transactions check_multiple_succesful_txs(web3, tx_to_confirm) end_balance = from_wei(web3.eth.getBalance(address), "ether") print("Deployment cost is", start_balance - end_balance, "ETH") print("All done! Enjoy your decentralized future.")
def main(chain, address, contract_name, name, symbol, supply, decimals, minting_agent, release_agent, verify, verify_filename, master_address): """Deploy a single crowdsale token contract. Examples: deploy-token --chain=ropsten --address=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6 --name="MikkoToken 2.0" --symbol=MOO --release-agent=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6 --supply=100000 deploy-token --chain=kovan --contract-name="CentrallyIssuedToken" --address=0x001FC7d7E506866aEAB82C11dA515E9DD6D02c25 --name="TestToken" --symbol=MOO --supply=916 --decimals=0 --verify --verify-filename=CentrallyIssuedToken.sol """ project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) print("Deployer address is", address) print("Deployer balance is", from_wei(web3.eth.getBalance(address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, address): request_account_unlock(c, address, None) decimal_multiplier = 10**decimals transaction = {"from": address} args = [name, symbol, supply * decimal_multiplier, decimals] if contract_name == "CentrallyIssuedToken": # TODO: Generalize settings contract args # This sets the upgrade master args = [address] + args # Make sure Populus does not pull up any cached instances of deployed contracts # TODO: Fix Populus support this via an deploy argument if "JSONFile" in c.registrar.registrar_backends: del c.registrar.registrar_backends["JSONFile"] print("Starting contract deployment") # This does deployment with all dependencies linked in contract, txhash = c.provider.deploy_contract( contract_name, deploy_transaction=transaction, deploy_args=args) check_succesful_tx(web3, txhash) print("Contract address is", contract.address) # This is needed for Etherscan contract verification # https://etherscanio.freshdesk.com/support/solutions/articles/16000053599-contract-verification-constructor-arguments const_args = get_constructor_arguments(contract, args) print("CrowdsaleToken constructor arguments is", const_args) if release_agent: print("Setting release agent to", release_agent) txid = contract.transact(transaction).setReleaseAgent( release_agent) check_succesful_tx(web3, txid) if minting_agent: print("Setting minting agent") txid = contract.transact(transaction).setMintAgent( minting_agent, True) check_succesful_tx(web3, txid) if master_address: print("Moving upgrade master to a team multisig wallet", master_address) txid = contract.transact({ "from": address }).setUpgradeMaster(master_address) check_succesful_tx(web3, txid) print("Moving total supply a team multisig wallet", master_address) contract.transact({ "from": address }).transfer(master_address, contract.call().totalSupply()) check_succesful_tx(web3, txid) if verify: chain_name = chain fname = verify_filename browser_driver = "chrome" verify_contract( project=project, libraries={}, # TODO: Figure out how to pass around chain_name=chain_name, address=contract.address, contract_name=contract_name, contract_filename=fname, constructor_args=const_args, # libraries=runtime_data["contracts"][name]["libraries"], browser_driver=browser_driver) link = get_etherscan_link(chain_name, contract.address) print("Verified contract is", link) print("Token supply:", contract.call().totalSupply()) # Do some contract reads to see everything looks ok try: print("Token owner:", contract.call().owner()) except ValueError: pass # No owner try: print("Token upgradeMaster:", contract.call().upgradeMaster()) except ValueError: pass try: print("Token minting finished:", contract.call().mintingFinished()) except ValueError: pass try: print("Token released:", contract.call().released()) print("Token release agent:", contract.call().releaseAgent()) except ValueError: pass print("All done! Enjoy your decentralized future.")
def main(): project = Project('populus.json') chain_name = "testrpclocal" print( "Make sure {} chain is running, you can connect to it, or you'll get timeout" .format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 print("Web3 provider is", web3.currentProvider) registry = deploy("Registry", chain) currencyNetworkFactory = deploy("CurrencyNetworkFactory", chain, registry.address) transfer_filter = currencyNetworkFactory.on("CurrencyNetworkCreated") txid = currencyNetworkFactory.transact({ "from": web3.eth.accounts[0] }).CreateCurrencyNetwork('Trustlines', 'T', web3.eth.accounts[0], 1000, 100, 25, 100) receipt = check_successful_tx(web3, txid) wait(transfer_filter) log_entries = transfer_filter.get() addr_trustlines = log_entries[0]['args']['_currencyNetworkContract'] print("Real CurrencyNetwork contract address is", addr_trustlines) resolver = deploy("Resolver", chain, addr_trustlines) receipt = check_successful_tx(web3, txid) transfer_filter = resolver.on("FallbackChanged") proxy = deploy("EtherRouter", chain, resolver.address) proxied_trustlines = chain.provider.get_contract_factory( "CurrencyNetwork")(proxy.address) txid = proxied_trustlines.transact({ "from": web3.eth.accounts[0] }).init('Trustlines', 'T', 6, 1000, 100, 25, 100) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("getUsers()", "getUsersReturnSize()", addr_trustlines) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("getFriends(address)", "getFriendsReturnSize(address)", addr_trustlines) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("trustline(address,address)", "trustlineLen(address,address)", addr_trustlines) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("getAccountExt(address,address)", "getAccountExtLen()", addr_trustlines) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("name()", "nameLen()", addr_trustlines) receipt = check_successful_tx(web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("symbol()", "symbolLen()", addr_trustlines) receipt = check_successful_tx(web3, txid) print("\n\naddress for accessing CurrencyNetwork through Proxy: ", proxied_trustlines.address, '\n\n')
import time import sys import datetime from decimal import Decimal import populus from populus.utils.accounts import is_account_locked from populus.utils.cli import request_account_unlock from populus import Project from eth_utils import to_wei from eth_utils import from_wei import utils from utils import check_succesful_tx from utils import get_contract_by_name from utils import get_constructor_arguments from utils import get_libraries from utils import * # from ico.etherscan import verify_contract import utils_yaml_cache from utils_yaml_cache import * p = project = PROJECT = Project(project_dir=PROJECT_DIR) print('end')
def main(chain, address, token_address, csv_file, limit, start_from, vault_address, address_column, amount_column, action, freeze_ends_at, tokens_to_be_allocated): """TokenVault control script. 1) Deploys a token vault contract 2) Reads in distribution data as CSV 3) Locks vault """ project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) print("Owner address is", address) print("Owner balance is", from_wei(web3.eth.getBalance(address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, address): request_account_unlock(c, address, timeout=3600 * 6) assert not is_account_locked(web3, address) Token = c.contract_factories.FractionalERC20 token = Token(address=token_address) print("Total supply is", token.functions.totalSupply().call()) try: decimals = token.functions.decimals().call() except ValueError: sys.exit( "Token contract does not have support for decimal places, cannot work with it" ) print("Token decimal places is", decimals) assert decimals >= 0 if action == "deploy": deploy(project, c, chain, web3, address, token, freeze_ends_at, tokens_to_be_allocated * (10**decimals)) print("TokenVault deployed.") sys.exit(0) elif action == "load": if vault_address == None: sys.exit("vault_address missing") if address_column == None: sys.exit("address_column missing") if amount_column == None: sys.exit("amount_column missing") load(c, web3, address, csv_file, token, address_column, amount_column, vault_address) print("Data loaded to the vault.") sys.exit(0) elif action == "lock": lock(c, web3, address, token, vault_address) print("Vault locked. Now duck and wait.") else: sys.exit("Unknown action: {}".format(action))
def main(chain, hot_wallet_address, csv_file, limit, start_from, address_column, amount_column, id_column, state_file): """Distribute ETh refunds. Reads in funds distribution data as CSV. Then sends funds from a local address. The refund status is stored as a JSON file. Example: refund --chain=kovan --hot-wallet-address=0x001fc7d7e506866aeab82c11da515e9dd6d02c25 --csv-file=refunds.csv --address-column="Refund address" --amount-column="ETH" --id-column="Email" --start-from=0 --limit=2 --state-file=refund-state.json Example CSV data: .. code-block:: csv Email,ETH,Refund address [email protected],61.52,0x0078EF811B6564c996fD10012579633B1a518b9D [email protected],111.21,0xf0b91641CCe2ADB4c0D7B90c54E7eE96CCCBc3d1 [email protected],61.52,0x0dAbC71Faa8982bF23eE2c4979d22536F5101065 [email protected],61.52,0x0B8EceBc18153166Beec1b568D510B55B560789D """ # Make a backup of the state file if os.path.exists(state_file): assert state_file.endswith(".json") backup_name = state_file.replace( ".json", "." + datetime.datetime.utcnow().isoformat() + ".bak.json") print("Backing up state file to", backup_name) shutil.copy(state_file, backup_name) project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.providers[0]) print("Hot wallet address is", hot_wallet_address) print("Hot wallet balance is", from_wei(web3.eth.getBalance(hot_wallet_address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, hot_wallet_address): request_account_unlock(c, hot_wallet_address, timeout=3600 * 6) assert not is_account_locked(web3, hot_wallet_address) print("Reading data", csv_file) with open(csv_file, "rt", encoding='utf-8-sig') as inp: reader = csv.DictReader(inp) rows = [row for row in reader] # Check that we have unique addresses uniq_ids = set() for row in rows: print(row) id = row[id_column].strip() if id in uniq_ids: raise RuntimeError("Id appears twice in input data", id) uniq_ids.add(id) addr = row[address_column] if not is_checksum_address(addr): print("Not a checksummed address", addr) # Start distribution start_time = time.time() start_balance = from_wei(web3.eth.getBalance(hot_wallet_address), "ether") print("Total rows", len(rows)) if os.path.exists(state_file): with open(state_file, "rt") as inp: state = json.load(inp) else: state = {} for i in range(start_from, min(start_from + limit, len(rows))): data = rows[i] addr = data[address_column].strip() id = data[id_column].strip() amount = Decimal(data[amount_column].strip()) amount_wei = to_wei(amount, "ether") if id in state: print("Already refunded", id, addr, amount) continue # Use non-default gas price for speedier processing gas_price = int(web3.eth.gasPrice * 3) txid = web3.eth.sendTransaction({ "from": hot_wallet_address, "to": addr, "value": amount_wei, "gasPrice": gas_price }) duration = time.time() - start_time print("Transferring", id, amount_wei, "to", addr, "txid", txid, "duration", duration) state[id] = txid with open(state_file, "wt") as out: json.dump(state, out) check_succesful_tx(web3, txid, timeout=300) end_balance = from_wei(web3.eth.getBalance(hot_wallet_address), "ether") print("Refund cost is", start_balance - end_balance, "ETH") print("All done! Enjoy your decentralized future.")
def project(project_dir, _loaded_contract_fixtures, _loaded_test_contract_fixtures): return Project()
def main(): project = Project() # This is configured in populus.json # We are working on a testnet chain_name = "local" print( "Make sure {} chain is running, you can connect to it, or you'll get timeout" .format(chain_name)) with project.get_chain(chain_name) as chain: web3 = Web3(RPCProvider()) print("Web3 provider is", web3.currentProvider) # Load Populus contract proxy classes Crowdsale = chain.get_contract_factory('Crowdsale') Token = chain.get_contract_factory('EdgelessToken') # The address who will be the owner of the contracts beneficiary = web3.eth.coinbase assert beneficiary, "Make sure your node has coinbase account created" # Generated account on local geth multisig_address = "0x6bcf2b956e6bb630954a7ffc7c6f42c0f60dfd80" # One generated account on local geth # MUST be unlocked customer = "0xc0addfc55b27886eb6c31a2a881b8ca979082b77" # Goes through coinbase account unlock process if needed get_unlocked_default_account_address(chain) # Deploy crowdsale, open since 1970 txhash = Crowdsale.deploy(transaction={"from": beneficiary}, args=[beneficiary, multisig_address, 1]) print("Deploying crowdsale, tx hash is", txhash) receipt = check_succesful_tx(web3, txhash) crowdsale_address = receipt["contractAddress"] print("Crowdsale contract address is", crowdsale_address) # Deploy token txhash = Token.deploy(transaction={"from": beneficiary}, args=[beneficiary]) print("Deploying token, tx hash is", txhash) receipt = check_succesful_tx(web3, txhash) token_address = receipt["contractAddress"] print("Token contract address is", token_address) # Make contracts aware of each other print("Initializing contracts") crowdsale = Crowdsale(address=crowdsale_address) token = Token(address=token_address) txhash = crowdsale.transact({ "from": beneficiary }).setToken(token_address) check_succesful_tx(web3, txhash) # Set the crowdfund approval limit txid = token.transact({ "from": beneficiary }).approve(crowdsale.address, 440000000) check_succesful_tx(web3, txid) token.call().allowance(beneficiary, crowdsale.address) == 440000000 # Give the customer some money print("Funding customer") txid = web3.eth.sendTransaction({ "from": web3.eth.coinbase, "to": customer, "value": to_wei(30, "ether"), }) check_succesful_tx(web3, txid) # Make one buy print("Making one crowdsale purchase") txid = web3.eth.sendTransaction({ "from": customer, "to": crowdsale.address, "value": to_wei(20, "ether"), "gas": 250000, }) check_succesful_tx(web3, txid) # Do some contract reads to see everything looks ok print("Token total supply is", token.call().totalSupply()) print("Crowdsale max goal is", crowdsale.call().maxGoal()) print("Customer has token balance", token.call().balanceOf(customer)) print("Tokens sold", crowdsale.call().tokensSold()) print("Multisig address is", multisig_address) print("Multisig balance is", web3.eth.getBalance(multisig_address)) print("Customer has crowdsale WEI balance", crowdsale.call().balanceOf(customer)) print("All done! Enjoy your decentralized future.")
def main(chain, address, csv_file): """Export issued events. Build a CSV file of run centralized token distribution. This can be later used to tell users what TXID gave them their tokens if we know the external id of the user. Example: export-issuance \ --address=0x0.... \ --csv-file=issued-test-drop.csv \ --chain=mainnet """ project = Project() timestamp_filename = "block-timestamps.json" with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) # Sanity check print("Block number is", web3.eth.blockNumber) IssuerWithId = c.provider.get_base_contract_factory('IssuerWithId') contract = IssuerWithId(address=address) CentrallyIssuedToken = c.provider.get_base_contract_factory( 'CentrallyIssuedToken') token = CentrallyIssuedToken(address=contract.functions.token().call()) decimals = token.functions.decimals().call() decimal_multiplier = 10**decimals print("Token", token.functions.symbol().call(), "has", decimals, "decimals, multiplier is", decimal_multiplier) print("Getting events") events = contract.events.Issued().createFilter( fromBlock=0).get_all_entries() print("Writing results to", csv_file) # Block number -> timestamp mappings timestamps = {} # Load cached timestamps if os.path.exists(timestamp_filename): with open(timestamp_filename, "rt") as inp: timestamps = json.load(inp) with open(csv_file, 'w', newline='') as out: writer = csv.writer(out) writer.writerow( ["External id", "Payment at", "Tx hash", "Received tokens"]) for idx, e in enumerate(events): if idx % 100 == 0: print("Writing event", idx) # Save cached timestamps with open(timestamp_filename, "wt") as out: json.dump(timestamps, out) block_number = e["blockNumber"] if block_number not in timestamps: timestamps[block_number] = web3.eth.getBlock( block_number)["timestamp"] amount = Decimal(e["args"]["amount"]) external_id = e["args"]["id"] tokens = amount / decimal_multiplier tokens = tokens.quantize(Decimal(10**-decimals)) timestamp = timestamps[block_number] dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) writer.writerow([ external_id, dt.isoformat(), e["transactionHash"], str(tokens), ]) print("Total", len(events), "issued events") print("All done! Enjoy your decentralized future.")
def main(chain, address, token, csv_file, limit, start_from, issuer_address, address_column, amount_column, allow_zero, master_address): """Distribute tokens to centrally issued crowdsale participant. Reads in distribution data as CSV. Then uses Issuer contract to distribute tokens. All token counts are multiplied by token contract decimal specifier. E.g. if CSV has amount 15.5, token has 2 decimal places, we will issue out 1550 raw token amount. To speed up the issuance, transactions are verified in batches. Each batch is 16 transactions at a time. Example (first run): distribute-tokens --chain=kovan --address=0x001FC7d7E506866aEAB82C11dA515E9DD6D02c25 --token=0x1644a421ae0a0869bac127fa4cce8513bd666705 --master-address=0x9a60ad6de185c4ea95058601beaf16f63742782a --csv-file=input.csv --allow-zero --address-column="Ethereum address" --amount-column="Token amount" Example (second run, continue after first run was interrupted): distribute-tokens --chain=kovan --address=0x001FC7d7E506866aEAB82C11dA515E9DD6D02c25 --token=0x1644a421ae0a0869bac127fa4cce8513bd666705 --csv-file=input.csv --allow-zero --address-column="Ethereum address" --amount-column="Token amount" --issuer-address=0x2c9877534f62c8b40aebcd08ec9f54d20cb0a945 """ project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.currentProvider) print("Owner address is", address) print("Owner balance is", from_wei(web3.eth.getBalance(address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, address): request_account_unlock(c, address, timeout=3600 * 6) assert not is_account_locked(web3, address) Token = c.provider.get_base_contract_factory('CentrallyIssuedToken') token = Token(address=token) print("Token is", token.address) print("Total supply is", token.call().totalSupply()) print("Upgrade master is", token.call().upgradeMaster()) print("Owner token balance master is", token.call().balanceOf(address)) decimals = token.call().decimals() print("Token decimal places is", decimals) assert decimals >= 0 decimal_multiplier = 10**decimals transaction = {"from": address} Issuer = c.provider.get_base_contract_factory('Issuer') if not issuer_address: # TODO: Fix Populus support this via an deploy argument if "JSONFile" in c.registrar.registrar_backends: del c.registrar.registrar_backends["JSONFile"] # Create issuer contract assert master_address, "You need to give master-address" args = [address, master_address, token.address] print("Deploying new issuer contract", args) issuer, txhash = c.provider.deploy_contract( "Issuer", deploy_transaction=transaction, deploy_args=args) check_succesful_tx(web3, txhash) const_args = get_constructor_arguments(issuer, args) chain_name = chain fname = "Issuer.sol" browser_driver = "chrome" verify_contract( project=project, libraries={}, # TODO: Figure out how to pass around chain_name=chain_name, address=issuer.address, contract_name="Issuer", contract_filename=fname, constructor_args=const_args, # libraries=runtime_data["contracts"][name]["libraries"], browser_driver=browser_driver) link = get_etherscan_link(chain_name, issuer.address) print("Issuer verified contract is", link) else: print("Reusing existing issuer contract") issuer = Issuer(address=issuer_address) print("Issuer contract is", issuer.address) print("Currently issued", issuer.call().issuedCount()) if not master_address: sys.exit( "Please use Token.approve() to give some allowance for the issuer contract by master address" ) allowance = token.call().allowance(master_address, issuer.address) print("Issuer allowance", allowance) if allowance == 0 or not master_address: sys.exit( "Please use Token.approve() to give some allowance for the issuer contract by master address" ) print("Reading data", csv_file) with open(csv_file, "rt") as inp: reader = csv.DictReader(inp) rows = [row for row in reader] # Check that we have unique addresses uniq_addresses = set() for row in rows: addr = row[address_column].strip() if addr in uniq_addresses: raise RuntimeError("Address appears twice in input data", addr) uniq_addresses.add(addr) # Start distribution start_time = time.time() start_balance = from_wei(web3.eth.getBalance(address), "ether") tx_to_confirm = [] # List of txids to confirm tx_batch_size = 16 # How many transactions confirm once print("Total rows", len(rows)) for i in range(start_from, min(start_from + limit, len(rows))): data = rows[i] addr = data[address_column].strip() tokens = Decimal(data[amount_column].strip()) tokens *= decimal_multiplier end_balance = from_wei(web3.eth.getBalance(address), "ether") spent = start_balance - end_balance if tokens == 0: if not allow_zero: raise RuntimeError("Encountered zero amount") else: continue # http://stackoverflow.com/a/19965088/315168 if not tokens % 1 == 0: raise RuntimeError( "Could not issue tokens because after multiplication was not integer" ) transaction = { "from": address, "gasPrice": int(web3.eth.gasPrice * 1.5) } tokens = int(tokens) print("Row", i, "giving", tokens, "to", addr, "issuer", issuer.address, "time passed", time.time() - start_time, "ETH passed", spent) if issuer.call().issued(addr): print("Already issued, skipping") continue txid = issuer.transact(transaction).issue(addr, tokens) tx_to_confirm.append(txid) # Confirm N transactions when batch max size is reached if len(tx_to_confirm) >= tx_batch_size: check_multiple_succesful_txs(web3, tx_to_confirm) tx_to_confirm = [] # Confirm dangling transactions check_multiple_succesful_txs(web3, tx_to_confirm) end_balance = from_wei(web3.eth.getBalance(address), "ether") print("Deployment cost is", start_balance - end_balance, "ETH") print("All done! Enjoy your decentralized future.")
def test_default_configuration_is_valid(project_dir): project = Project(project_dir) assert project._config_schema is not None project.config.validate()
def main(**kwargs): project = Project() chain_name = kwargs['chain'] owner = kwargs['owner'] challenge_period = kwargs['challenge_period'] supply = kwargs['supply'] token_name = kwargs['token_name'] token_decimals = kwargs['token_decimals'] token_symbol = kwargs['token_symbol'] token_address = kwargs['token_address'] supply *= 10**(token_decimals) txn_wait = 250 assert challenge_period >= 500, 'Challenge period should be >= 500 blocks' if chain_name == 'rinkeby': txn_wait = 500 print( '''Make sure {} chain is running, you can connect to it and it is synced, or you'll get timeout'''.format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 print('Web3 provider is', web3.providers[0]) # Temporary fix for Rinkeby; PoA adds bytes to extraData, which is not yellow-paper-compliant # https://github.com/ethereum/web3.py/issues/549 if int(web3.version.network) == 4: txn_wait = 500 size_extraData_for_poa = 200 # can change pythonic_middleware.__closure__[2].cell_contents[ 'eth_getBlockByNumber'].args[1].args[0][ 'extraData'] = to_hexbytes(size_extraData_for_poa, variable_length=True) pythonic_middleware.__closure__[2].cell_contents[ 'eth_getBlockByHash'].args[1].args[0][ 'extraData'] = to_hexbytes(size_extraData_for_poa, variable_length=True) owner = owner or web3.eth.accounts[0] assert owner and is_address(owner), 'Invalid owner provided.' owner = to_checksum_address(owner) print('Owner is', owner) assert web3.eth.getBalance( owner) > 0, 'Account with insuficient funds.' token = chain.provider.get_contract_factory('TestMOS') if not token_address: txhash = token.deploy( args=[supply, token_name, token_symbol, token_decimals], transaction={'from': owner}) time.sleep(180) receipt = check_succesful_tx(chain.web3, txhash, txn_wait) token_address = receipt['contractAddress'] assert token_address and is_address(token_address) token_address = to_checksum_address(token_address) print(token_name, 'address is', token_address) microraiden_contract = chain.provider.get_contract_factory( 'RaidenMicroTransferChannels') txhash = microraiden_contract.deploy( args=[token_address, challenge_period, []], transaction={'from': owner}) time.sleep(180) receipt = check_succesful_tx(chain.web3, txhash, txn_wait) microraiden_address = receipt['contractAddress'] print('RaidenMicroTransferChannels address is', microraiden_address)
def main(): project = Project('populus.json') chain_name = "testrpclocal" print( "Make sure {} chain is running, you can connect to it, or you'll get timeout" .format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 print("Web3 provider is", web3.currentProvider) registry = deploy("Registry", chain) currencyNetworkFactory = deploy("CurrencyNetworkFactory", chain, registry.address) transfer_filter = currencyNetworkFactory.on("CurrencyNetworkCreated") txid = currencyNetworkFactory.transact({ "from": web3.eth.accounts[0] }).CreateCurrencyNetwork('Trustlines', 'T', web3.eth.accounts[0], 1000, 100, 100) receipt = check_successful_tx("create", web3, txid) wait(transfer_filter) log_entries = transfer_filter.get() addr_trustlines = log_entries[0]['args']['_currencyNetworkContract'] print("REAL CurrencyNetwork contract address is", addr_trustlines) resolver = deploy("Resolver", chain, addr_trustlines) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("getAccountExt(address,address)", "getAccountExtLen()", addr_trustlines) receipt = check_successful_tx("resolver", web3, txid) transfer_filter = resolver.on("FallbackChanged") proxy = deploy("EtherRouter", chain, resolver.address) proxied_trustlines = chain.provider.get_contract_factory( "CurrencyNetwork")(proxy.address) txid = proxied_trustlines.transact({ "from": web3.eth.accounts[0] }).setAccount(web3.eth.accounts[6], web3.eth.accounts[7], 2000000, 1, 1, 1, 1, 1, 1, 1) receipt = check_successful_tx("setAccount", web3, txid) print(proxied_trustlines.call().getAccountExt(web3.eth.accounts[6], web3.eth.accounts[7])) storagev2 = deploy("CurrencyNetwork", chain) txid = resolver.transact({ "from": web3.eth.accounts[0] }).setFallback(storagev2.address) receipt = check_successful_tx("setFallback", web3, txid) wait(transfer_filter) log_entries = transfer_filter.get() print("Forwarded to ", log_entries[0]['args']['newFallback']) txid = proxied_trustlines.transact({ "from": web3.eth.accounts[0] }).init('Trustlines', 'T', 6, 1000, 100, "0x0000000000000000000000000000000000000000") receipt = check_successful_tx("init", web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("getAccountExt(address,address)", "getAccountExtLen()", storagev2.address) receipt = check_successful_tx("register", web3, txid) txid = resolver.transact({ "from": web3.eth.accounts[0] }).registerLengthFunction("trustline(address,address)", "trustlineLen(address,address)", storagev2.address) receipt = check_successful_tx("register", web3, txid) print(proxied_trustlines.call().getAccountExt(web3.eth.accounts[6], web3.eth.accounts[7])) prepare_trustlines_contract(proxied_trustlines, web3) test_trustlines(proxied_trustlines, web3) test_mediated_transfer_array(proxied_trustlines, web3)
def main(chain, address, token, csv_file, limit, start_from, issuer_address, address_column, amount_column, external_id_column, allow_addresless, master_address, gas_price, solc_version): """Distribute tokens to centrally issued crowdsale participant or bounty program participants using an external key. Reads in distribution data as CSV. Then uses Issuer contract to distribute tokens. All token counts are multiplied by token contract decimal specifier. E.g. if CSV has amount 15.5, token has 2 decimal places, we will issue out 1550 raw token amount. The external id uniquely identifies participants. This is different from the distribute-tokens where the Ethereum address uniquely identifies participants. To speed up the issuance, transactions are verified in batches. Each batch is 16 transactions at a time. First have a issuer contract created: distribute-tokens-ext-id \ --chain=mainnet \ --address=0xccba4928c4e9d10242788d9cf144d865348c6c7f \ --token=0x1a7a8bd9106f2b8d977e08582dc7d24c723ab0db \ --master-address=0xa684a3371e0d46bca4a6db1ff538a44f1440a855 \ --csv-file=data.csv \ --address-column="Ethereum address" \ --amount-column="Token amount" \ --external-id-column="External ID number" \ --solc-version="v0.4.16+commit.d7661dd9" \ --gas-price=100 Then perform EIP-20 approve() to give tokens to the issuer contract deployed in the last command. Then run the distribution: distribute-tokens-ext-id \ --chain=mainnet \ --address=0xccba4928c4e9d10242788d9cf144d865348c6c7f \ --token=0x1a7a8bd9106f2b8d977e08582dc7d24c723ab0db \ --master-address=0xa684a3371e0d46bca4a6db1ff538a44f1440a855 \ --issuer-address=0x60cfb02266310e66dd99b1635e702c519a564726 \ --csv-file=combined.csv \ --address-column="Address" \ --amount-column="Amount" \ --gas-price=70 \ --start-from=670 """ project = Project() with project.get_chain(chain) as c: web3 = c.web3 print("Web3 provider is", web3.providers[0]) print("Deployer account address is", address) print("Deployer account balance is", from_wei(web3.eth.getBalance(address), "ether"), "ETH") # Goes through geth account unlock process if needed if is_account_locked(web3, address): request_account_unlock(c, address, timeout=3600 * 6) assert not is_account_locked(web3, address) Token = c.provider.get_base_contract_factory('CentrallyIssuedToken') token = Token(address=token) print("Token is", token.address) print("Total supply is", token.functions.totalSupply().call()) print("Upgrade master is", token.functions.upgradeMaster().call()) print("Deployer account token balance is", token.functions.balanceOf(address).call()) decimals = token.functions.decimals().call() print("Token decimal places is", decimals) assert decimals >= 0 decimal_multiplier = 10**decimals if gas_price: gas_price = int(gas_price) * 10**9 else: gas_price = web3.eth.gasPrice * 2 transaction = {"from": address, "gasPrice": gas_price} print("Using gas price of", gas_price / 10**9, "GWei") IssuerWithId = c.provider.get_base_contract_factory('IssuerWithId') if not issuer_address: # TODO: Fix Populus support this via an deploy argument if "JSONFile" in c.registrar.registrar_backends: del c.registrar.registrar_backends["JSONFile"] # Create issuer contract assert master_address, "You need to give master-address" args = [address, master_address, token.address] print("Deploying new issuer contract", args, "transaction parameters", transaction) issuer, txhash = c.provider.deploy_contract( "IssuerWithId", deploy_transaction=transaction, deploy_args=args) print("Deployment transaction is", txhash) print("Waiting contract to be deployed") check_succesful_tx(web3, txhash) const_args = get_constructor_arguments(issuer, args) print("Contract constructor arguments are", const_args) chain_name = chain fname = "IssuerWithId.sol" browser_driver = "chrome" verify_contract( project=project, libraries={}, # TODO: Figure out how to pass around chain_name=chain_name, address=issuer.address, contract_name="IssuerWithId", contract_filename=fname, constructor_args=const_args, browser_driver=browser_driver, compiler=solc_version) link = get_etherscan_link(chain_name, issuer.address) print("Issuer verified contract is", link) else: print("Using existing issuer contract") issuer = IssuerWithId(address=issuer_address) print("Issuer contract is", issuer.address) print("Currently issued", issuer.functions.issuedCount().call()) if not master_address: sys.exit( "Please use Token.approve() to give some allowance for the issuer contract by master address" ) allowance = token.functions.allowance(master_address, issuer.address).call() print("Issuer allowance", allowance) if allowance == 0 or not master_address: sys.exit( "Please use Token.approve() to give some allowance for the issuer contract by master address" ) print("Reading data", csv_file) with open(csv_file, "rt") as inp: reader = csv.DictReader(inp) rows = [row for row in reader] # Prevalidate addresses # For distributetokens.py this is done by combine-csv # Here we do it inline and make skip addresses that are not valid. for idx, row in enumerate(rows): addr = row[address_column].strip() try: if addr: validate_ethereum_address(addr) except ValueError as e: print("Invalid Ethereum address on row:", idx + 1, "address:", addr, "reason:", str(e), "external_id:", row[external_id_column]) # Proceed regardless of invalid data row[address_column] = "" # Start distribution start_time = time.time() start_balance = from_wei(web3.eth.getBalance(address), "ether") tx_to_confirm = [] # List of txids to confirm tx_batch_size = 16 # How many transactions confirm once print("Total rows", len(rows)) for i in range(start_from, min(start_from + limit, len(rows))): data = rows[i] addr = data[address_column].strip() external_id = data[external_id_column].strip() tokens = Decimal(data[amount_column].strip()) tokens *= decimal_multiplier end_balance = from_wei(web3.eth.getBalance(address), "ether") spent = start_balance - end_balance if addr == "": if not allow_addresless: raise RuntimeError("Encountered missing address") else: continue if not external_id: raise RuntimeError("Missing external id on row #{}".format(i + 1)) # http://stackoverflow.com/a/19965088/315168 if not tokens % 1 == 0: raise RuntimeError( "Could not issue tokens because after multiplication was not integer" ) transaction = { "from": address, "gasPrice": gas_price, "gas": 100000, # Use 100k gas unit limit } tokens = int(tokens) external_id = int(external_id) if not external_id > 0: raise RuntimeError( "External id must be a positive integer on row #{}".format( i + 1)) print("Row", i, "giving", tokens, "to", addr, "issuer", issuer.address, "time passed", time.time() - start_time, "ETH passed", spent, "gas price", transaction["gasPrice"] / (10**9)) if issuer.functions.issued(external_id).call(): print("Already issued, skipping") continue txid = issuer.functions.issue(addr, tokens, external_id).transact(transaction) tx_to_confirm.append(txid) # Confirm N transactions when batch max size is reached if len(tx_to_confirm) >= tx_batch_size: check_multiple_succesful_txs(web3, tx_to_confirm) tx_to_confirm = [] # Confirm dangling transactions check_multiple_succesful_txs(web3, tx_to_confirm) end_balance = from_wei(web3.eth.getBalance(address), "ether") print("Deployment cost is", start_balance - end_balance, "ETH") print("All done! Enjoy your decentralized future.")
def main(): project = Project() chain_name = "tester" print( "Make sure {} chain is running, you can connect to it, or you'll get timeout" .format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 print("Web3 providers are", web3.providers) creator = web3.eth.accounts[0] ursula = web3.eth.accounts[1] alice = web3.eth.accounts[2] # Create an ERC20 token token, txhash = chain.provider.get_or_deploy_contract( 'HumanStandardToken', deploy_args=[10**9, 10**10, 'NuCypher KMS', 6, 'KMS'], deploy_transaction={'from': creator}) check_succesful_tx(web3, txhash) print("Deploying HumanStandardToken, tx hash is", txhash) # Creator deploys the escrow escrow, txhash = chain.provider.get_or_deploy_contract( 'Escrow', deploy_args=[token.address, 10**5, 10**7], deploy_transaction={'from': creator}) check_succesful_tx(web3, txhash) print("Deploying Escrow, tx hash is", txhash) # Give Ursula and Alice some coins tx = token.transact({'from': creator}).transfer(ursula, 10000) chain.wait.for_receipt(tx) tx = token.transact({'from': creator}).transfer(alice, 10000) chain.wait.for_receipt(tx) print("Estimate gas for checking balance = " + str(token.estimateGas().balanceOf(alice))) # Ursula and Alice give Escrow rights to transfer print("Estimate gas for approving = " + str( token.estimateGas({ 'from': ursula }).approve(escrow.address, 1000))) tx = token.transact({'from': ursula}).approve(escrow.address, 1000) chain.wait.for_receipt(tx) tx = token.transact({'from': alice}).approve(escrow.address, 500) chain.wait.for_receipt(tx) # Ursula and Alice transfer some tokens to the escrow and lock them print("Estimate gas for deposit = " + str(escrow.estimateGas({ 'from': ursula }).deposit(1000, 100))) tx = escrow.transact({'from': ursula}).deposit(1000, 100) chain.wait.for_receipt(tx) tx = escrow.transact({'from': alice}).deposit(500, 200) chain.wait.for_receipt(tx) # Give rights for mining print( "Estimate gas for giving rights for mining = " + str(token.estimateGas({ 'from': creator }).addMiner(escrow.address))) tx = token.transact({'from': creator}).addMiner(escrow.address) chain.wait.for_receipt(tx) # Wait 150 blocks and mint tokens chain.wait.for_block(web3.eth.blockNumber + 150) print("Estimate gas for Ursula mining = " + str(escrow.estimateGas({ 'from': ursula }).mint())) tx = escrow.transact({'from': ursula}).mint() chain.wait.for_receipt(tx) # Wait 100 blocks and mint tokens chain.wait.for_block(web3.eth.blockNumber + 100) print("Estimate gas for Alice mining = " + str(escrow.estimateGas({ 'from': alice }).mint())) tx = escrow.transact({'from': alice}).mint() chain.wait.for_receipt(tx) # Creator deploys the wallet manager wallet_manager, txhash = chain.provider.get_or_deploy_contract( 'WalletManager', deploy_args=[token.address, 10**5, 10**7], deploy_transaction={'from': creator}) check_succesful_tx(web3, txhash) print("Deploying WalletManager, tx hash is", txhash) print("Estimate gas for creating wallet = " + str(wallet_manager.estimateGas({ 'from': ursula }).createWallet())) contract_factory = chain.provider.get_contract_factory("Wallet") tx = wallet_manager.transact({'from': ursula}).createWallet() chain.wait.for_receipt(tx) ursula_wallet = contract_factory( address=wallet_manager.call().wallets(ursula)) tx = wallet_manager.transact({'from': alice}).createWallet() chain.wait.for_receipt(tx) alice_wallet = contract_factory( address=wallet_manager.call().wallets(alice)) # Give Ursula and Alice some coins tx = token.transact({'from': creator}).transfer(ursula, 10000) chain.wait.for_receipt(tx) tx = token.transact({'from': creator}).transfer(alice, 10000) chain.wait.for_receipt(tx) # Ursula and Alice transfer some money to wallets print("Estimate gas for deposit = " + str( token.estimateGas({ 'from': ursula }).transfer(ursula_wallet.address, 1000))) tx = token.transact({ 'from': ursula }).transfer(ursula_wallet.address, 1000) chain.wait.for_receipt(tx) tx = token.transact({ 'from': alice }).transfer(alice_wallet.address, 500) chain.wait.for_receipt(tx) # Ursula and Alice lock some tokens for 100 and 200 blocks print( "Estimate gas for locking = " + str(wallet_manager.estimateGas({ 'from': ursula }).lock(1000, 100))) tx = wallet_manager.transact({'from': ursula}).lock(1000, 100) chain.wait.for_receipt(tx) tx = wallet_manager.transact({'from': alice}).lock(500, 200) chain.wait.for_receipt(tx) # Give rights for mining tx = token.transact({'from': creator}).addMiner(wallet_manager.address) chain.wait.for_receipt(tx) # Wait 150 blocks and mint tokens chain.wait.for_block(web3.eth.blockNumber + 150) print("Estimate gas for Ursula mining = " + str(wallet_manager.estimateGas({ 'from': ursula }).mint())) tx = wallet_manager.transact({'from': ursula}).mint() chain.wait.for_receipt(tx) # Wait 100 blocks and mint tokens chain.wait.for_block(web3.eth.blockNumber + 100) print("Estimate gas for Alice mining = " + str(wallet_manager.estimateGas({ 'from': alice }).mint())) tx = wallet_manager.transact({'from': alice}).mint() chain.wait.for_receipt(tx) print("All done!")