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.call().totalSupply())

        try:
            decimals = token.call().decimals()
        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, address, token_address, csv_file, limit, start_from, vault_address, address_column, amount_column, duration_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.providers[0])
        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('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, duration_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))
Beispiel #3
0
def test_with_locked_account(project):
    temp_chain = project.get_chain('temp')

    account = force_text(
        create_new_account(temp_chain.geth.data_dir, b'a-test-password'))

    with temp_chain:
        web3 = temp_chain.web3

        assert account in web3.eth.accounts
        assert is_account_locked(web3, account) is True

        assert web3.personal.unlockAccount(account, 'a-test-password')

        assert is_account_locked(web3, account) is False
def test_with_locked_account(project):
    temp_chain = project.get_chain('temp')

    account = force_text(
        create_new_account(temp_chain.geth.data_dir, b'a-test-password')
    )

    with temp_chain:
        web3 = temp_chain.web3

        assert account in web3.eth.accounts
        assert is_account_locked(web3, account) is True

        assert web3.personal.unlockAccount(account, 'a-test-password')

        assert is_account_locked(web3, account) is False
Beispiel #5
0
def main(chain, address, name, symbol, supply, minting_agent, release_agent):
    """Rebuild a relaunched CrowdsaleToken contract.

    Example:

    deploy-token --chain=ropsten --address=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6 --name="MikkoToken 2.0" --symbol=MOO --release-agent=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6  --supply=100000

    """

    raise NotImplementedError()

    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, None)

        transaction = {"from": address}
        args = [name, symbol, supply]

        # This does deployment with all dependencies linked in

        print("Starting contract deployment")
        contract, txhash = c.provider.deploy_contract(
            'CrowdsaleToken', deploy_transaction=transaction, deploy_args=args)
        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
        data = get_constructor_arguments(contract, args)
        print("CrowdsaleToken constructor arguments is", data)

        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)

        # Do some contract reads to see everything looks ok
        print("Token owner:", contract.call().owner())
        print("Token minting finished:", contract.call().mintingFinished())
        print("Token released:", contract.call().released())
        print("Token release agent:", contract.call().releaseAgent())

        print("All done! Enjoy your decentralized future.")
Beispiel #6
0
def deploy_contract(project: Project,
                    chain,
                    deploy_address,
                    contract_def: dict,
                    chain_name: str,
                    need_unlock=True) -> Contract:
    """Deploy a single contract.

    :param need_unlock: Do the account unlock procedure (disable for testrpc)
    """

    web3 = chain.web3

    contract_name = contract_def["contract_name"]

    version = web3.version.node

    # Goes through geth account unlock process if needed
    if need_unlock and version.startswith("Geth"):
        # TODO:  Parity does not support this, must unlock on a command line, or web ui?
        if is_account_locked(web3, deploy_address):
            # Deploy can last max 1 h
            request_account_unlock(chain, deploy_address, timeout=3600)

    transaction = {"from": deploy_address}
    kwargs = dict(**contract_def["arguments"])  # Unwrap YAML CommentedMap

    print("Starting", contract_name, "deployment, with arguments ", kwargs)

    # TODO: Workaround when deploying the same contract twice in run,
    # because Populus contract_identity allows only one contract_identity per contract class
    # print(chain.registrar.contract_addresses)
    # if "JSONFile" in chain.registrar.registrar_backends:
    #    del chain.registrar.registrar_backends["JSONFile"]
    # chain.registrar.registrar_backends["Memory"].contract_addresses = defaultdict(set)

    try:
        contract, txhash = chain.provider.deploy_contract(
            contract_name,
            deploy_transaction=transaction,
            deploy_kwargs=kwargs)
    except Exception as e:
        raise RuntimeError(
            "Could not deploy contract {}, constructor arguments {}".format(
                contract_name, kwargs)) from e

    contract_def["address"] = contract.address
    print(contract_name, "address is", contract.address)

    constructor_args = get_constructor_arguments(contract, kwargs=kwargs)
    print(contract_name, "constructor arguments payload is", constructor_args)
    contract_def["constructor_args"] = constructor_args

    libraries = get_libraries(chain, contract_name, contract)
    print(contract_name, "libraries are", libraries)
    contract_def["libraries"] = libraries

    return contract
def main(chain, address, cosigners, required):
    """Deploy a multisig wallet contract.

    Example of creating a multisig wallet with 2/3 cosigners required:

    deploy-multisig --chain=ropsten --address=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6  --cosigners=0xa5384627F6DcD3440298E2D8b0Da9d5F0FCBCeF7,0xD947F285Dbf2098C248133209cb92343e44e9BA8 --required=2
    """

    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, None)

        transaction = {"from": address}

        cosigners = cosigners.split(",")
        args = [cosigners, required, 0]

        # This does deployment with all dependencies linked in

        print("Starting contract deployment")

        # This will giv you TypeError: One or more arguments could not be encoded to the necessary ABI type if any of the addresses is not valid
        contract, txhash = c.provider.deploy_contract(
            'Wallet', deploy_transaction=transaction, deploy_args=args)
        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
        data = get_constructor_arguments(contract, args)
        print("Contract constructor arguments is", data)

        # Do some contract reads to see everything looks ok
        for i in range(0, 10):
            owner = contract.call().getOwner(i)

            if owner == "0x0000000000000000000000000000000000000000":
                # EVM gives you null value if you do array out of bounds
                break

            print("Wallet cosigner #{}:".format(i + 1), owner)
            if owner == "0x0":
                break

        print("Number of cosigners required for execution:",
              contract.call().m_required())
        print("Wallet balance:", web3.eth.getBalance(contract.address))
        print("All done! Enjoy your decentralized future.")
Beispiel #8
0
def test_request_account_unlock_with_bad_password(project_dir):
    project = Project()
    chain = project.get_chain('temp')

    # create 3 new accounts
    account = force_text(
        create_new_account(chain.geth.data_dir, b'a-test-password'))

    @click.command()
    def wrapper():
        request_account_unlock(chain, account, None)

    with chain:
        assert is_account_locked(chain.web3, account)

        runner = CliRunner()
        result = runner.invoke(wrapper, [], input="bad-password\n")

        assert result.exit_code != 0
        assert is_account_locked(chain.web3, account)
def test_request_account_unlock_with_bad_password(project_dir):
    project = Project()
    chain = project.get_chain('temp')

    # create 3 new accounts
    account = force_text(
        create_new_account(chain.geth.data_dir, b'a-test-password')
    )

    @click.command()
    def wrapper():
        request_account_unlock(chain, account, None)

    with chain:
        assert is_account_locked(chain.web3, account)

        runner = CliRunner()
        result = runner.invoke(wrapper, [], input="bad-password\n")

        assert result.exit_code != 0
        assert is_account_locked(chain.web3, account)
def deploy_contract(project: Project, chain, deploy_address, contract_def: dict, chain_name: str, need_unlock=True) -> Contract:
    """Deploy a single contract.

    :param need_unlock: Do the account unlock procedure (disable for testrpc)
    """

    web3 = chain.web3

    contract_name = contract_def["contract_name"]

    version = web3.version.node

    # Goes through geth account unlock process if needed
    if need_unlock and version.startswith("Geth"):
        # TODO:  Parity does not support this, must unlock on a command line, or web ui?
        if is_account_locked(web3, deploy_address):
            # Deploy can last max 1 h
            request_account_unlock(chain, deploy_address, timeout=3600)

    # Use non-default gas price for speedier processing
    gas_price = int(web3.eth.gasPrice * 1.2)

    transaction = {"from": deploy_address, "gasPrice": gas_price}
    kwargs = dict(**contract_def["arguments"])  # Unwrap YAML CommentedMap

    print("Starting", contract_name, "deployment, with arguments ", kwargs)

    # TODO: Workaround when deploying the same contract twice in run,
    # because Populus contract_identity allows only one contract_identity per contract class
    if "JSONFile" in chain.registrar.registrar_backends:
        del chain.registrar.registrar_backends["JSONFile"]
    chain.registrar.registrar_backends["Memory"].contract_addresses = defaultdict(set)

    try:
        contract, txhash = chain.provider.deploy_contract(contract_name, deploy_transaction=transaction, deploy_kwargs=kwargs)
    except Exception as e:
        raise RuntimeError("Could not deploy contract {}, constructor arguments {}".format(contract_name, kwargs)) from e

    contract_def["address"] = contract.address
    print(contract_name, "address is", contract.address)

    constructor_args = get_constructor_arguments(contract, kwargs=kwargs)
    print(contract_name, "constructor arguments payload is", constructor_args)
    contract_def["constructor_args"] = constructor_args

    libraries = get_libraries(chain, contract_name, contract)
    print(contract_name, "libraries are", libraries)
    contract_def["libraries"] = libraries

    return contract
Beispiel #11
0
def deploy_contract(project: Project,
                    chain,
                    deploy_address,
                    contract_def: dict,
                    chain_name: str,
                    need_unlock=True) -> Contract:
    """Deploy a single contract.

    :param need_unlock: Do the account unlock procedure (disable for testrpc)
    """

    web3 = chain.web3

    contract_name = contract_def["contract_name"]

    # Goes through geth account unlock process if needed
    if need_unlock:
        if is_account_locked(web3, deploy_address):
            # Deploy can last max 1 h
            request_account_unlock(chain, deploy_address, timeout=3600)

    transaction = {"from": deploy_address}
    kwargs = dict(**contract_def["arguments"])  # Unwrap YAML CommentedMap

    print("Starting", contract_name, "deployment, with arguments ", kwargs)
    try:
        contract, txhash = chain.provider.deploy_contract(
            contract_name,
            deploy_transaction=transaction,
            deploy_kwargs=kwargs)
    except Exception as e:
        raise RuntimeError(
            "Could not deploy contract {}, constructor arguments {}".format(
                contract_name, kwargs)) from e

    contract_def["address"] = contract.address
    print(contract_name, "address is", contract.address)

    constructor_args = get_constructor_arguments(contract, kwargs=kwargs)
    print(contract_name, "constructor arguments payload is", constructor_args)
    contract_def["constructor_args"] = constructor_args

    libraries = get_libraries(chain, contract_name, contract)
    print(contract_name, "libraries are", libraries)
    contract_def["libraries"] = libraries

    return contract
Beispiel #12
0
# Owner account on geth
owner_address = "0x2b317defb1d07e737ef9dacd88bf1daeb5a54da3"

# Where did we deploy our token
contract_address = "0x0aa721cc960c65b341f5663af620819148034ae1"

project = populus.Project()

with project.get_chain(chain_name) as chain:

    web3 = chain.web3
    print("Web3 provider is", web3.currentProvider)
    print("Owner address is", owner_address)
    print("Owner balance is",
          from_wei(web3.eth.getBalance(owner_address), "ether"), "ETH")

    # Goes through geth account unlock process if needed
    if is_account_locked(web3, owner_address):
        request_account_unlock(chain, owner_address, None)

    print("contract addr:", chain.provider.get_all_contract_data())
    transaction = {"from": owner_address}
    #Contract = chain.get_contract_factory("CrowdsaleToken")
    Contract = getattr(chain.contract_factories, "CrowdsaleToken")

    contract = Contract(address=contract_address)
    print("Attempting to release the token transfer")
    txid = contract.transact(transaction).releaseTokenTransfer()
    check_succesful_tx(web3, txid)
    print("Token released")
Beispiel #13
0
crowdsale_address = config['contracts']['crowdsale'][3][1]
price_address = config['contracts']['pricing_strategy'][3][1]
finalize_address = config['contracts']['finalize_agent'][3][1]

project = populus.Project()

with project.get_chain(chain_name) as chain:

    web3 = chain.web3
    print("Web3 provider is", web3.currentProvider)
    print("Participant address is", participant_address)
    print("Participant balance is",
          from_wei(web3.eth.getBalance(participant_address), "ether"), "ETH")

    # Goes through geth account unlock process if needed
    if is_account_locked(web3, participant_address):
        request_account_unlock(chain, participant_address, None)

    print("contract addr:", chain.provider.get_all_contract_data())
    transaction = {"from": participant_address}

    Contract = getattr(chain.contract_factories, "MintedTokenCappedCrowdsale")
    crowdsale = Contract(address=crowdsale_address)

    Contract = getattr(chain.contract_factories, "FlatPricing")
    pricingStrategy = Contract(address=price_address)

    Contract = getattr(chain.contract_factories, "BonusFinalizeAgent")
    finalizeAgent = Contract(address=finalize_address)

    Contract = getattr(chain.contract_factories, "CrowdsaleToken")
Beispiel #14
0
def main(chain, address, owner, days, minimum, verify):
    """Deploy a PresaleFundCollector contract.

    Example:

     deploy-presale --chain=ropsten --address=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6  --owner=0x3c2d4e5eae8c4a31ccc56075b5fd81307b1627c6 --days=30 --minimum=30

    """
    project = Project()

    # Parse command line args to presale constructor args
    minimum = to_wei(minimum, "ether")
    freeze_ends_at = int(utc_time() + days * 24 * 3600)

    contract_name = "PresaleFundCollector"

    # This is configured in populus.json
    # We are working on a testnet
    print(
        "Make sure {} chain is running, you can connect to it, or you'll get timeout"
        .format(chain))

    with project.get_chain(chain) as c:

        web3 = c.web3
        print("Web3 provider is", web3.currentProvider)
        print("Deploy address is", address)
        if not address:
            sys.exit(
                "You need to explicitly give the address from where we are deploying from"
            )

        print("Deploy address balance is",
              from_wei(web3.eth.getBalance(address), "ether"))

        # Goes through geth account unlock process if needed
        if is_account_locked(web3, address):
            request_account_unlock(c, address, None)

        transaction = {"from": address}
        args = [owner, freeze_ends_at, minimum]

        # This does deployment with all dependencies linked in
        print("Deploying contracts")
        presale, txhash = c.provider.deploy_contract(
            contract_name, deploy_transaction=transaction, deploy_args=args)
        print("Deploying presale, tx hash is", txhash)
        print("Presale contract address is", presale.address)

        libraries = get_libraries(c, contract_name, presale)
        print("Linked libraries are", libraries)

        # This is needed for Etherscan contract verification
        # https://etherscanio.freshdesk.com/support/solutions/articles/16000053599-contract-verification-constructor-arguments
        constructor_args = get_constructor_arguments(presale, args)
        print("Presale constructor arguments is", constructor_args)

        if verify:
            print("Verifying contract")
            verify_contract(project=project,
                            chain_name=chain,
                            address=presale.address,
                            contract_name="PresaleFundCollector",
                            contract_filename="PresaleFundCollector.sol",
                            constructor_args=constructor_args,
                            libraries=libraries)

        # Do some contract reads to see everything looks ok
        print("Presale freeze ends at", presale.call().freezeEndsAt())
        print("Presale minimum buy in (wei) is",
              presale.call().weiMinimumLimit())

        # Estimate invest() gas cost
        estimation = presale.estimateGas(transaction={
            "from": address,
            "value": to_wei(1000, "ether")
        }).invest()
        print("Presale.invest() estimated gas cost is", estimation)

        sig_data = presale._prepare_transaction("invest")
        print("Presale.invest() data payload is", sig_data["data"])

        sig_data = presale._prepare_transaction("refund")
        print("Presale.refund() data payload is", sig_data["data"])

        print("All done! Enjoy your decentralized future.")
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.functions.tokensSold().call())

        assert relaunched_crowdsale.functions.owner().call(
        ) == address, "We are not the crowdsale owner. Real owner is {}, we are {}".format(
            relaunched_crowdsale.functions.owner().call(), 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)
            }

            # 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, "gas price",
                  transaction["gasPrice"])

            if relaunched_crowdsale.functions.getRestoredTransactionStatus(
                    orig_txid).call():
                print("Already restored, skipping")
                continue

            tokens = int(tokens)

            if cap_check:
                # See if our cap calculation is screwed
                if relaunched_crowdsale.functions.isBreakingCap(
                        wei, tokens,
                        relaunched_crowdsale.functions.weiRaised().call(),
                        relaunched_crowdsale.functions.tokensSold().call()
                ).call():
                    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.")
Beispiel #16
0
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.

    THIS COMMAND IS DEPRECATED. PLEASE USE deploy-contracts instead.

    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.functions.setReleaseAgent(release_agent).transact(
                transaction)
            check_succesful_tx(web3, txid)

        if minting_agent:
            print("Setting minting agent")
            txid = contract.functions.setMintAgent(minting_agent,
                                                   True).transact(transaction)
            check_succesful_tx(web3, txid)

        if master_address:
            print("Moving upgrade master to a team multisig wallet",
                  master_address)
            txid = contract.functions.setUpgradeMaster(
                master_address).transact({"from": address})
            check_succesful_tx(web3, txid)
            print("Moving total supply a team multisig wallet", master_address)
            contract.functions.transfer(
                master_address,
                contract.functions.totalSupply().call()).transact(
                    {"from": address})
            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.functions.totalSupply().call())

        # Do some contract reads to see everything looks ok
        try:
            print("Token owner:", contract.functions.owner().call())
        except ValueError:
            pass  # No owner

        try:
            print("Token upgradeMaster:",
                  contract.functions.upgradeMaster().call())
        except ValueError:
            pass

        try:
            print("Token minting finished:",
                  contract.functions.mintingFinished().call())
        except ValueError:
            pass

        try:
            print("Token released:", contract.functions.released().call())
            print("Token release agent:",
                  contract.functions.releaseAgent().call())
        except ValueError:
            pass

        print("All done! Enjoy your decentralized future.")
Beispiel #17
0
CROWDSALE_ADDRESS = CACHE[FIELDNAME.CROWDSALE_ADDRESS]

print('CONTRACT_NAME = {}'.format(CONTRACT_NAME))
print('crowdlsale add = {}'.format(CROWDSALE_ADDRESS))

value_to_buy = to_wei(0.000000001, 'ETHER')
print('Value_to_buy = {}'.format(value_to_buy))
print('Buyer = {}'.format(account))

with p.get_chain(CHAIN) as chain:
    web3 = chain.web3
    Crowdsale = get_contract_by_name(chain, CONTRACT_NAME)
    crowdsale = Crowdsale(address=CROWDSALE_ADDRESS)
    #     crowdsale = Crowdsale(address=CROWDSALE_TOKEN_ADDRESS)

    if is_account_locked(web3, account):
        request_account_unlock(chain, account, None)
#     print('get res = {}'.format(crowdsale.call().getRes()))

#     crowdsale = CROWDSALE_ADDRESS

#     print('opcodes = {}'.format(contract.call().opcodes()))
    customer_id = int(uuid.uuid4().hex, 16)  # Customer ids are 128-bit UUID v4

    txid = crowdsale.transact({
        'from': account,
        'sender': account,
        'value': value_to_buy,
    }).buy()

    print('somem form of buy completed')
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.")
Beispiel #19
0
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.currentProvider)
        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.call().decimals()
        logger.info("Total supply is %s",
                    token.call().totalSupply() / (10**decimals))
        logger.info("Owner account token balance is %s",
                    token.call().balanceOf(owner_address) / (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.")
Beispiel #20
0
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 --csv-file=input.csv --allow-zero --address-column="Ethereum address" --amount-column="Golden tickets earned"

    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="Golden tickets earned" --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("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")

            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 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 or bounty program participants.

    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.")
Beispiel #22
0
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.currentProvider)
        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.")
Beispiel #23
0
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.currentProvider)
        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.")
Beispiel #24
0
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
    """

    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)

        transaction = {"from": address}

        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_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")
        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")
            tokens = int(data["Received tokens"])
            orig_txid = int(data["Tx hash"], 16)
            # orig_tx_index = int(data["Tx index"])

            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

            txid = relaunched_crowdsale.transact(
                transaction).setInvestorDataAndIssueNewToken(
                    addr, wei, tokens, orig_txid)
            check_succesful_tx(web3, txid)

        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, 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.currentProvider)
        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.")