Esempio n. 1
0
    def _convert_balance_to_wad(self, balance: dict, decimals: int) -> dict:
        wei_balance = float(balance['wei'])
        pending_balance = float(balance['pendingWei'])

        ## DyDx can have negative balances from native margin trading
        is_negative = False
        if wei_balance < 0:
            is_negative = True

        converted_balance = from_wei(abs(int(wei_balance)), 'ether')
        converted_pending_balance = from_wei(abs(int(pending_balance)),
                                             'ether')

        if decimals == 6:
            converted_balance = from_wei(abs(int(wei_balance)), 'mwei')
            converted_pending_balance = from_wei(abs(int(pending_balance)),
                                                 'mwei')

        # reconvert Wad to negative value if balance is negative
        if is_negative == True:
            converted_balance = converted_balance * -1

        # Handle the edge case where orders are filled but balance change is still pending
        if converted_balance > 0:
            balance['wad'] = Wad.from_number(
                converted_balance) - Wad.from_number(converted_pending_balance)
        else:
            balance['wad'] = Wad.from_number(
                converted_balance) + Wad.from_number(converted_pending_balance)

        return balance
Esempio n. 2
0
def deploy_crowdsale_from_file(project: Project, yaml_filename: str,
                               deployment_name: str, deploy_address: str):
    """Deploy crowdsale plan."""
    chain_data = load_crowdsale_definitions(yaml_filename, deployment_name)
    chain_name = chain_data["chain"]
    address = deploy_address

    with project.get_chain(chain_name) as chain:

        web3 = chain.web3

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

        runtime_data, statistics, contracts = deploy_crowdsale(
            project, chain, chain_data, deploy_address)
        perform_post_actions(chain, runtime_data, contracts)
        perform_verify_actions(chain, runtime_data, contracts)
        write_deployment_report(yaml_filename, runtime_data)
        end_balance = from_wei(web3.eth.getBalance(address), "ether")
        print("Deployment cost is", start_balance - end_balance, "ETH")

    return runtime_data, statistics, contracts
Esempio n. 3
0
def ProcessEpoch(block_number):
    block = getBlock(block_number)
    epoch_number, e, created = createEpoch(block_number, block)
    log.info('Processing Epoch #{0}'.format(int(epoch_number)))

    rewards = getRewardsByHash(to_hex(block.hash))

    if rewards is None:
        return None

    if not 'rewards' in rewards:
        return None
    signer_checksum = 0
    reward_checksum = 0
    for candidate in rewards['signers']:
        candidate = rpc.toChecksumAddress(candidate)
        validator, created = createAccount(candidate, True, block_number)
        signer_reward = from_wei(
            rewards['signers'][candidate.lower()]['reward'], 'ether')
        signer, created = Signers.objects.get_or_create(
            account=validator,
            epoch=e,
            defaults={
                'account': validator,
                'epoch': e,
                'sign': rewards['signers'][candidate.lower()]['sign'],
                'awarded': e.timestamp,
                'amount': signer_reward,
            })
        if created:
            signer.save()
        for account in rewards['rewards'][candidate.lower()]:
            account = rpc.toChecksumAddress(account)
            voter, created = createAccount(account, False, block_number)
            reward_amount = from_wei(
                rewards['rewards'][candidate.lower()][account.lower()],
                'ether')
            r, created = Reward.objects.get_or_create(
                account=voter,
                epoch=e,
                candidate=validator,
                defaults={
                    'account':
                    voter,
                    'epoch':
                    e,
                    'candidate':
                    validator,
                    'awarded':
                    pytz.utc.localize(
                        datetime.fromtimestamp(float(block.timestamp))),
                    'amount':
                    reward_amount,
                })
            reward_checksum += reward_amount
            if created:
                r.save()
Esempio n. 4
0
def populate_tweet_text_from_market(market, tweet_text, decorations):
    market_title = market["name"]

    market_title = process_market_title(market_title)

    market_type = market["type"]

    market_slug = market["slug"]

    market_url = VEIL_MARKET_URL + market_slug

    market_channel = market["channel"]

    # compose the tweet
    tweet_text.append("\"")
    tweet_text.append(market_title)
    tweet_text.append("\"")

    # scalar work
    if (market_type == "scalar"):
        market_denomination = market["denomination"]

        # format correctly for USD denomination
        market_min_price = market["min_price"]
        market_min_price = str(from_wei(int(market_min_price), 'ether'))
        if (market_denomination == "USD"):
            market_min_price = "{:,.2f}".format(float(market_min_price))

        market_max_price = market["max_price"]
        market_max_price = str(from_wei(int(market_max_price), 'ether'))
        if (market_denomination == "USD"):
            market_max_price = "{:,.2f}".format(float(market_max_price))

        tweet_text.append(" (")
        tweet_text.append(str(market_min_price))
        tweet_text.append(" ")
        tweet_text.append(market_denomination)
        tweet_text.append(" - ")
        tweet_text.append(str(market_max_price))
        tweet_text.append(" ")
        tweet_text.append(market_denomination)
        tweet_text.append(")")

    tweet_text.append(" ")
    tweet_text.append(market_url)

    # append channel as a hashtag if possible
    if (market_channel != None):
        tweet_text.append(" #")
        tweet_text.append(market_channel)

        if (market_channel in decorations):
            # append this channel's emoji decoration
            tweet_text.append(" ")
            tweet_text.append(decorations[market_channel])
Esempio n. 5
0
def main(chain, address, csv_file):
    """Extract crowdsale invested events.

    This is useful for RelaunchCrowdsale to rebuild the data.
    """

    project = Project()

    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_contract_factory(
            'MintedTokenCappedCrowdsale')
        crowdsale = Crowdsale(address=address)

        print("Total amount raised is",
              from_wei(crowdsale.call().weiRaised(), "ether"), "ether")

        print("Getting events")
        events = crowdsale.pastEvents("Invested").get(only_changes=False)

        print("Writing results to", csv_file)
        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 e in events:
                timestamp = web3.eth.getBlock(e["blockNumber"])["timestamp"]
                dt = datetime.datetime.fromtimestamp(timestamp,
                                                     tz=datetime.timezone.utc)
                writer.writerow([
                    address,
                    dt.isoformat(),
                    e["transactionHash"],
                    e["transactionIndex"],
                    from_wei(e["args"]["weiAmount"], "ether"),
                    e["args"]["tokenAmount"],
                ])

        print("Total", len(events), "invest events")
        print("All done! Enjoy your decentralized future.")
Esempio n. 6
0
 def payment_form_render(self, request: HttpRequest,
                         total: decimal.Decimal):
     # this ensures that the form will pre-populate the transaction hash into the form.
     if 'txhash' in request.GET:
         request.session['payment_ethereum_txn_hash'] = request.GET.get(
             'txhash')
     if 'currency' in request.GET:
         request.session[
             'payment_ethereum_currency_type'] = request.GET.get('currency')
     form = self.payment_form(request)
     template = get_template('pretix_eth/checkout_payment_form.html')
     ctx = {
         'request':
         request,
         'form':
         form,
         'ETH_per_ticket':
         from_wei(self._get_rates_from_api(total, 'ETH'), 'ether'),
         'DAI_per_ticket':
         self._get_rates_from_api(total, 'DAI'),
         'ETH_address':
         self.settings.get('ETH'),
         'DAI_address':
         self.settings.get('DAI'),
     }
     return template.render(ctx)
def test_buy_all(chain, web3, crowdsale, token, finalizer, start_time, end_time, team_multisig, customer, cap, founder_allocation):
    """Buy all tokens and finalize crowdsale."""

    # Buy on first week
    time_travel(chain, start_time + 1)
    assert crowdsale.call().getState() == CrowdsaleState.Funding

    # Buy all cap
    wei_value = cap
    print(from_wei(web3.eth.getBalance(customer), "ether"))
    crowdsale.transact({"from": customer, "value": wei_value}).buy()
    assert crowdsale.call().isCrowdsaleFull()

    # Close the deal
    time_travel(chain, end_time + 1)
    assert crowdsale.call().getState() == CrowdsaleState.Success
    crowdsale.transact({"from": team_multisig}).finalize()
    assert crowdsale.call().getState() == CrowdsaleState.Finalized

    # See that we counted bonus correctly
    team_bonus = token.call().totalSupply() * 7 / 10
    assert abs(finalizer.call().allocatedBonus() - team_bonus) < 10  # We lose some in decimal rounding

    # Token is transferable
    assert token.call().released()
Esempio n. 8
0
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))
Esempio n. 9
0
def queue_reward(
    *,
    deposit: Deposit,
    dbsession: Session,
    web3: Web3,
    reward_amount_rbtc: Decimal,
    deposit_thresholds: RewardThresholdMap,
):
    threshold = deposit_thresholds.get(deposit.side_token_symbol)
    if not threshold:
        # TODO: maybe these should be added somewhere for post processing?
        logger.warning('Threshold not found for deposit %s -- cannot process',
                       deposit)
        return
    if deposit.amount_decimal < threshold:
        logger.info('Threshold %s not met for deposit %s -- not rewarding',
                    threshold, deposit)
        return

    existing_reward = dbsession.query(Reward).filter(
        func.lower(Reward.user_address) ==
        deposit.user_address.lower()).first()
    if existing_reward:
        logger.info('User %s has already been rewarded.', deposit.user_address)
        return

    [balance, transaction_count] = _get_user_balance_and_transaction_count(
        web3=web3,
        user_address=deposit.user_address.lower(),
    )
    if balance > 0:
        logger.info(
            'User %s has an existing balance of %s RBTC - not rewarding',
            deposit.user_address, from_wei(balance, 'ether'))
        return
    if transaction_count > 0:
        logger.info(
            'User %s already has %s transactions in RSK - not rewarding',
            deposit.user_address, transaction_count)
        return

    logger.info('Rewarding user %s with %s RBTC', deposit.user_address,
                str(reward_amount_rbtc))

    reward = Reward(
        status=RewardStatus.queued,
        reward_rbtc_wei=int(reward_amount_rbtc * 10**18),
        user_address=deposit.user_address,
        deposit_side_token_address=deposit.side_token_address,
        deposit_side_token_symbol=deposit.side_token_symbol,
        deposit_main_token_address=deposit.main_token_address,
        deposit_amount_minus_fees_wei=deposit.amount_minus_fees_wei,
        deposit_log_index=deposit.log_index,
        deposit_block_hash=deposit.block_hash,
        deposit_transaction_hash=deposit.transaction_hash,
        deposit_contract_address=deposit.contract_address,
    )
    dbsession.add(reward)
    dbsession.flush()
    return reward
def test_proxy_buy_load_refund(chain, web3, customer, customer_2,
                               team_multisig, proxy_buyer, crowdsale, token):
    """Fail the crowdsale, refund the pre-investors"""

    assert proxy_buyer.call().getState() == 1

    proxy_buyer.transact({
        "value": to_wei(10000, "ether"),
        "from": customer
    }).buy()

    # Move over
    assert crowdsale.call().getState() == CrowdsaleState.Funding
    proxy_buyer.transact({
        "from": team_multisig
    }).setCrowdsale(crowdsale.address)
    assert proxy_buyer.call().crowdsale() == crowdsale.address
    proxy_buyer.transact({"from": customer}).buyForEverybody()

    proxy_buyer.transact({"from": team_multisig}).forceRefund()
    proxy_buyer.transact({
        "value": to_wei(10000, "ether"),
        "from": customer
    }).loadRefund()

    before_refund = web3.eth.getBalance(customer)
    proxy_buyer.transact({"from": customer}).refund()
    after_refund = web3.eth.getBalance(customer)

    assert from_wei(after_refund - before_refund,
                    "ether") > 0.99  # gas cost epsilon
Esempio n. 11
0
def test_refund(failed_ico_ready_to_refund: Contract, web3: Web3,
                customer: str, customer_2: str):
    """Customers can claim their refunds."""

    assert failed_ico_ready_to_refund.functions.loadedRefund().call(
    ) == to_wei(120, "ether")
    assert failed_ico_ready_to_refund.functions.getState().call(
    ) == CrowdsaleState.Refunding

    # Check that the customer gets money back
    invested_amount = failed_ico_ready_to_refund.functions.investedAmountOf(
        customer).call()
    begin_balance = web3.eth.getBalance(customer)
    failed_ico_ready_to_refund.functions.refund().transact({"from": customer})
    end_balance = web3.eth.getBalance(customer)

    eth = from_wei(end_balance - begin_balance,
                   "ether")  # Decimal('49.999999999999954693')
    assert (end_balance - begin_balance) >= eth - TRANSACTION_COST_ETH_EPSILON

    failed_ico_ready_to_refund.functions.refund().transact(
        {"from": customer_2})

    # Everything has been refunded
    assert failed_ico_ready_to_refund.functions.weiRefunded().call() == to_wei(
        120, "ether")
Esempio n. 12
0
def test_invest_presale_refund(chain, web3, presale_fund_collector,
                               presale_crowdsale, preico_starts_at, customer,
                               customer_2):
    """We can refund"""

    value = to_wei(1, "ether")
    presale_fund_collector.transact({
        "from": customer,
        "value": value
    }).invest()

    value = to_wei(1.5, "ether")
    presale_fund_collector.transact({
        "from": customer_2,
        "value": value
    }).invest()

    time_travel(chain, presale_fund_collector.call().freezeEndsAt() + 1)

    before_refund = web3.eth.getBalance(customer)
    presale_fund_collector.transact({"from": customer}).refund()
    after_refund = web3.eth.getBalance(customer)

    assert from_wei(after_refund - before_refund,
                    "ether") > 0.99  # gas cost epsilon
    assert presale_fund_collector.call().balances(customer) == 0
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 proxy_buyers(project, chain, web3, customer, everything_deployed,
                 deploy_address, proxy_buyer_freeze_ends_at,
                 presale_investor_1, presale_investor_2, presale_investor_3,
                 presale_investor_4):
    """Simulate the presale contracts."""

    crowdsale = everything_deployed["crowdsale"]
    pricing_strategy = everything_deployed["pricing_strategy"]

    # Presale price
    default_presale_price = from_wei(2500000000000000, "ether")

    # List of presale contracts
    proxy_buyers = [
        (presale_investor_1, "9930.441837", default_presale_price),
        (presale_investor_2, "9999",
         default_presale_price),  # 0x6d997eDcA04282950416FA380d834f360fC36eBb
    ]

    results = []
    for investor, amount, price, in proxy_buyers:
        # Create finalizer contract
        amount = Decimal(amount)

        # Dummy presale min and max arguments
        args = [
            deploy_address,
            proxy_buyer_freeze_ends_at,
            1,  # 1 wei,
            to_wei(10000, "ether"),
            to_wei(10000, "ether"),
        ]
        proxy_buyer, hash = chain.provider.deploy_contract('PreICOProxyBuyer',
                                                           deploy_args=args)

        # Load presale contract with money
        assert proxy_buyer.call().getState() == 1
        proxy_buyer.transact({
            "value": to_wei(amount, "ether"),
            "from": investor
        }).buy()

        # Set ICO
        proxy_buyer.transact({
            "from": deploy_address
        }).setCrowdsale(crowdsale.address)

        # Set proxy buyer contract special price
        pricing_strategy.transact({
            "from": deploy_address
        }).setPreicoAddress(proxy_buyer.address, to_wei(price, "ether"))

        # Allow proxy buyer to move money in early
        crowdsale.transact({
            "from": deploy_address
        }).setEarlyParicipantWhitelist(proxy_buyer.address, True)

        results.append(proxy_buyer)

    return results
Esempio n. 15
0
def test_buy_all(chain, web3, crowdsale, token, finalizer, start_time, end_time, team_multisig, customer, cap, founder_allocation):
    """Buy all tokens and finalize crowdsale."""

    # Buy on first week
    time_travel(chain, start_time + 1)
    assert crowdsale.functions.getState().call() == CrowdsaleState.Funding

    # Buy all cap
    wei_value = cap
    print(from_wei(web3.eth.getBalance(customer), "ether"))
    crowdsale.functions.buy().transact({"from": customer, "value": wei_value})
    assert crowdsale.functions.isCrowdsaleFull().call()

    # Close the deal
    time_travel(chain, end_time + 1)
    assert crowdsale.functions.getState().call() == CrowdsaleState.Success
    crowdsale.functions.finalize().transact({"from": team_multisig})
    assert crowdsale.functions.getState().call() == CrowdsaleState.Finalized

    # See that we counted bonus correctly
    team_bonus = token.functions.totalSupply().call() * 7 / 10
    assert abs(finalizer.functions.allocatedBonus().call() - team_bonus) < 10  # We lose some in decimal rounding

    # Token is transferable
    assert token.functions.released().call()
Esempio n. 16
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.")
Esempio n. 17
0
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.")
Esempio n. 18
0
def broadcast(
    logger: Logger,
    dbsession: Session,
    network: str,
    ethereum_node_url: Union[str, Web3],
    ethereum_private_key: str,
    ethereum_gas_limit: Optional[str],
    ethereum_gas_price: Optional[str],
    commit=True,
):
    """Issue out a new Ethereum token."""

    check_good_private_key(ethereum_private_key)

    web3 = create_web3(ethereum_node_url)

    service = EthereumStoredTXService(network, dbsession, web3,
                                      ethereum_private_key, ethereum_gas_price,
                                      ethereum_gas_limit, BroadcastAccount,
                                      PreparedTransaction)

    service.ensure_accounts_in_sync()

    pending_broadcasts = service.get_pending_broadcasts()

    logger.info("Pending %d transactions for broadcasting in network %s",
                pending_broadcasts.count(), network)

    if pending_broadcasts.count() == 0:
        logger.info(
            "No new transactions to broadcast. Use sto tx-update command to see tx status."
        )
        return []

    account = Account.privateKeyToAccount(ethereum_private_key)
    balance = web3.eth.getBalance(account.address)

    logger.info("Our address %s has ETH balance of %f for operations",
                account.address, from_wei(balance, "ether"))

    txs = list(pending_broadcasts)
    # https://stackoverflow.com/questions/41985993/tqdm-show-progress-for-a-generator-i-know-the-length-of
    for tx in tqdm(txs, total=pending_broadcasts.count()):
        try:
            service.broadcast(tx)
            # logger.info("Broadcasted %s", tx.txid)
        except Exception as e:
            logger.exception(e)
            logger.error("Failed to broadcast transaction %s: %s", tx.txid,
                         tx.human_readable_description)
            raise e

        if commit:
            dbsession.commit()  # Try to minimise file system sync issues

    return txs
Esempio n. 19
0
def createVote(_vote, vote, block_number, e, unvote=False):
    v, created = Vote.objects.get_or_create(tx=vote.transactionHash)
    if created:
        log.debug('create voter')
        voter = rpc.toChecksumAddress(_vote._voter)
        vo, created = createAccount(voter, False, vote.blockNumber)
        candidate, created = createCandidate(_vote._candidate, None,
                                             block_number, e)
        v.candidate = candidate.candidate
        v.epoch = e
        v.account = vo
        v.tx = vote.transactionHash
        v.block_number = vote.blockNumber
        if unvote:
            v.amount = 0 - from_wei(_vote._cap, 'ether')
        else:
            v.amount = from_wei(_vote._cap, 'ether')
        v.save()
    return v, created
Esempio n. 20
0
def fetch_transactions(bids):
    txs = []
    hashes = bids['txhash'].unique()
    for hash_ in hashes:
        tx = dict(web3.eth.getTransaction(hash_))
        tx['value'] = from_wei(tx['value'], 'ether')
        txs.append(tx)
    keys = txs[0].keys()
    d = {key: [tx[key] for tx in txs] for key in txs[0].keys()}
    return pd.DataFrame(d)
Esempio n. 21
0
def gas_price() -> int:
    w3 = get_infura_web3()
    try:
        # 5% + 5 gwei above infura
        price = int(float(from_wei(w3.eth.gasPrice, 'gwei')) * 1.05) + 5
        assert price > 0
    except:
        price = GAS_PRICE

    return price
Esempio n. 22
0
    def from_message(trade, pair: str, market_info: dict) -> Trade:
        decimal_exponent = 18 - int(market_info['quoteCurrency']['decimals'])
        price = Wad.from_number(float(trade['price']) * 10 ** decimal_exponent)

        return Trade(trade_id=trade['uuid'],
                     timestamp=int(dateutil.parser.parse(trade['createdAt']).timestamp()),
                     pair=trade["market"],
                     is_sell=True if trade['side'] == 'SELL' else False,
                     price=price,
                     amount=Wad.from_number(from_wei(abs(int(float(trade['amount']))), 'ether')))
Esempio n. 23
0
    def from_message(item: list, pair: str, market_info: dict) -> Order:
        decimal_exponent = 18 - int(market_info['quoteCurrency']['decimals'])
        price = Wad.from_number(float(item['price']) * 10 ** decimal_exponent)

        return Order(order_id=item['id'],
                     timestamp=int(dateutil.parser.parse(item['createdAt']).timestamp()),
                     pair=pair,
                     is_sell=True if item['side'] == 'SELL' else False,
                     price=price,
                     amount=Wad.from_number(from_wei(abs(int(float(item['baseAmount']))), 'ether')))
Esempio n. 24
0
def participate_early(chain, web3: Web3, presale_address: str, crowdsale_address: str, deploy_address: str, start=0, end=32, timeout=300) -> int:
    """Move funds over early.

    .. note ::

        Crowdsale contract checks the participate whitelist by invest address, not by msg.sender.
        This process will open the presale investors an ability to participate to the crowdsale early,
        bypassing the retail investor start time. However they could also top up their existing
        preico accounts, so this is largerly no issue.


    :param start: Move only n investors (for testing purposes)
    :param end: Move only n investors (for testing purposes)
    """

    updated = 0

    PresaleFundCollector = get_contract_by_name(chain, "PresaleFundCollector")
    presale = PresaleFundCollector(address=presale_address)

    Crowdsale = PresaleFundCollector = get_contract_by_name(chain, "Crowdsale")
    crowdsale = Crowdsale(address=crowdsale_address)

    # Make sure presale is correctly set
    txid = presale.transact({"from": deploy_address}).setCrowdsale(crowdsale.address)
    logger.info("Setting presale crowdsale address to %s on txid", crowdsale.address, txid)
    check_succesful_tx(web3, txid, timeout=timeout)

    # Double check presale has a presale price set
    MilestonePricing = get_contract_by_name(chain, "MilestonePricing")
    pricing_strategy = MilestonePricing(address=crowdsale.call().pricingStrategy())

    if not pricing_strategy.call().preicoAddresses(presale.address):
        raise RuntimeError("Was not listed as presale address for pricing: {}".format(presale.address))

    for i in range(start, min(end, presale.call().investorCount())):

        investor = presale.call().investors(i)

        if presale.call().balances(investor) > 0:
            print("Whitelisting for {} to crowdsale {}".format(investor, crowdsale.address))
            txid = crowdsale.transact({"from": deploy_address}).setEarlyParicipantWhitelist(investor, True)
            print("Broadcasting whitelist transaction {}".format(txid))
            check_succesful_tx(web3, txid, timeout=timeout)

            funds = from_wei(presale.call().balances(investor), "ether")
            print("Moving funds {} ETH for investor {} to presale {}".format(funds, investor, presale.address))
            txid = presale.transact({"from": deploy_address}).participateCrowdsaleInvestor(investor)
            print("Broadcasting transaction {}".format(txid))
            check_succesful_tx(web3, txid, timeout=timeout)
            updated += 1
        else:
            print("Investor already handled: {}".format(investor))

    return updated
Esempio n. 25
0
def fetch_txs(bids):
    txs = []
    for txhash in bids['txhash']:
        tx = dict(web3.eth.getTransaction(txhash))
        tx['value'] = from_wei(tx['value'], 'ether')
        txs.append(tx)
    tx_df = pd.DataFrame(
        {key: [tx[key] for tx in txs]
         for key in txs[0].keys()})
    tx_df = tx_df.set_index('hash')
    return tx_df
Esempio n. 26
0
    def _convert_balance_to_wad(self, balance: dict, decimals: int) -> dict:
        wei_balance = float(balance['wei'])

        ## DyDx can have negative balances from native margin trading
        is_negative = False
        if wei_balance < 0:
            is_negative = True

        converted_balance = from_wei(abs(int(wei_balance)), 'ether')

        if decimals == 6:
            converted_balance = from_wei(abs(int(wei_balance)), 'mwei')

        # reconvert Wad to negative value if balance is negative
        if is_negative == True:
            converted_balance = converted_balance * -1

        balance['wad'] = Wad.from_number(converted_balance)

        return balance
Esempio n. 27
0
def _deploy_contracts(project, chain, web3, yaml_filename, chain_data, deploy_address):
    """Kernel for deploing contracts."""

    # Coinbase aliasing
    if deploy_address == "coinbase":
        deploy_address = web3.eth.accounts[0]

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

    runtime_data, statistics, contracts = deploy_crowdsale(project, chain, yaml_filename, chain_data, deploy_address)
    perform_post_actions(chain, runtime_data, contracts)
    perform_verify_actions(chain, runtime_data, contracts)
    write_deployment_report(yaml_filename, runtime_data)
    end_balance = from_wei(web3.eth.getBalance(address), "ether")
    print("Deployment cost is", start_balance - end_balance, "ETH")
    return runtime_data, statistics, contracts
Esempio n. 28
0
def _deploy_contracts(project, chain, web3, yaml_filename, chain_data, deploy_address):
    """
    :param project:
    :param chain:
    :param chain_data:
    :param deploy_address:
    :return:
    """

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

    runtime_data, statistics, contracts = deploy_crowdsale(project, chain, chain_data, deploy_address)
    perform_post_actions(chain, runtime_data, contracts)
    perform_verify_actions(chain, runtime_data, contracts)
    write_deployment_report(yaml_filename, runtime_data)
    end_balance = from_wei(web3.eth.getBalance(address), "ether")
    print("Deployment cost is", start_balance - end_balance, "ETH")
    return runtime_data, statistics, contracts
def _deploy_contracts(project, chain, web3, yaml_filename, chain_data, deploy_address):
    """
    :param project:
    :param chain:
    :param chain_data:
    :param deploy_address:
    :return:
    """

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

    runtime_data, statistics, contracts = deploy_crowdsale(project, chain, yaml_filename, chain_data, deploy_address)
    perform_post_actions(chain, runtime_data, contracts)
    perform_verify_actions(chain, runtime_data, contracts)
    write_deployment_report(yaml_filename, runtime_data)
    end_balance = from_wei(web3.eth.getBalance(address), "ether")
    print("Deployment cost is", start_balance - end_balance, "ETH")
    return runtime_data, statistics, contracts
Esempio n. 30
0
def does_block_meet_min_gas_price(block, chain):
    average_gas_price_in_wei = get_block_average_transaction_gas_price(block) #in wei
    required_min_gas_price_in_gwei = chain.min_gas_db.get_required_block_min_gas_price() #in gwei

    if average_gas_price_in_wei == float('inf'):
        return True

    average_gas_price_in_gwei = from_wei(average_gas_price_in_wei, 'gwei')

    if average_gas_price_in_gwei < required_min_gas_price_in_gwei:
        return False
    else:
        return True
Esempio n. 31
0
def fetch_bids():
    """Get all bid events and return them as a dataframe."""
    block_range = {'fromBlock': CONTRACT_CREATION_BLOCK}
    # get bid events
    log_filter = auction_contract.on('BidSubmission', block_range)
    events = log_filter.get(only_changes=False)
    df = pd.DataFrame({
        'amount':
        [from_wei(event['args']['_amount'], 'ether') for event in events],
        'missing': [
            from_wei(event['args']['_missing_funds'], 'ether')
            for event in events
        ],
        'sender': [event['args']['_sender'] for event in events],
        'block': [event['blockNumber'] for event in events],
        'txhash': [event['transactionHash'] for event in events]
    })

    # get start time of auction
    log_filter = auction_contract.on('AuctionStarted',
                                     {'fromBlock': CONTRACT_CREATION_BLOCK})
    start_events = log_filter.get(only_changes=False)
    assert len(start_events) == 1
    start_time = start_events[0]['args']['_start_time']
    print(start_time)

    # get bid times
    blocks = df['block'].unique()
    timestamps = []
    for block_number in blocks:
        block = web3.eth.getBlock(int(block_number))
        timestamps.append(block['timestamp'] - start_time)
    timestamp_df = pd.DataFrame({'block': blocks, 'time': timestamps})
    merged = pd.merge(df, timestamp_df, on='block')

    # sort by time and return
    sorted = merged.sort_values('time')
    return sorted
Esempio n. 32
0
def ProcessMasternodes(block_num):
    log.info(
        '\tProcessing masternode validation at block {0}.'.format(block_num))
    #blk = api.models.block.Block.objects.get(id=block_id)
    blk = rpc.eth.getBlock(to_hex(block_num))
    signer_req_data = {
        'jsonrpc': '2.0',
        'method': 'eth_getCandidates',
        'params': ['latest'],
        'id': settings.CHAIN_ID,
    }
    result = requests.post(url=settings.RESTFUL_ENDPOINT, json=signer_req_data)
    data = result.json()['result']

    for c in data['candidates']:
        d = data['candidates'][c]
        owner = validator.functions.getCandidateOwner(c).call()
        cand = api.models.shifu.Candidate.objects.filter(
            smartContractAddress=settings.VALIDATOR_CONTRACT_ADDRESS,
            candidate=c)
        if len(cand) < 1:
            cand = api.models.shifu.Candidate()
        else:
            cand = cand[0]
        cand.smartContractAddress = settings.VALIDATOR_CONTRACT_ADDRESS
        cand.owner = owner
        cand.candidate = c
        cand.status = d['status']
        cand.capacity = d['capacity']
        cand.capacityNumber = from_wei(d['capacity'], 'ether')
        if d['status'] == 'MASTERNODE' or d['status'] == 'SLASHED':
            cand.latestBlock = blk.number
            cand.totalSignedBlocks = api.models.block.BlockSigner.objects.filter(
                signers__icontains=c).count()
            lsb = api.models.block.BlockSigner.objects.filter(
                signers__icontains=c).order_by('-blockNumber')
            if len(lsb) > 0:
                cand.lastSignedBlock = lsb[0].blockNumber
        cand.save()
        ProcessVoters(c, block_num)

    # update top 150 rankings
    top150 = api.models.shifu.Candidate.objects.values('id').annotate(
        capacity_cap=Count('capacityNumber')).order_by('-capacity_cap')[:150]
    rank = 1
    for x in top150:
        _c = api.models.shifu.Candidate.objects.get(id=x['id'])
        _c.rank = rank
        _c.save()
        rank += 1
Esempio n. 33
0
    async def create_wallet(self):
        addr, priv = self.create_addr()
        price = await self.get_gas_price()
        single_tx_price = price * self.MAX_GAS
        single_tx_price = from_wei(single_tx_price, 'ether')
        try:
            await self.send_eth(
                settings.BUFFER_ETH_PRIV,
                [(addr, single_tx_price * self.LND_WALLETS_TOPUP_TRANS_NO)],
            )
        except NotEnoughAmountError:
            raise GeneralError("not enough eth in buffer wallet")

        return addr, priv
def proxy_buyers(project, chain, web3, customer, everything_deployed, deploy_address, proxy_buyer_freeze_ends_at, presale_investor_1, presale_investor_2, presale_investor_3, presale_investor_4):
    """Simulate the presale contracts."""

    crowdsale = everything_deployed["crowdsale"]
    pricing_strategy = everything_deployed["pricing_strategy"]

    # Presale price
    default_presale_price = from_wei(2500000000000000, "ether")

    # List of presale contracts
    proxy_buyers = [
        (presale_investor_1, "9930.441837", default_presale_price),
        (presale_investor_2, "9999", default_presale_price),# 0x6d997eDcA04282950416FA380d834f360fC36eBb
    ]

    results = []
    for investor, amount, price, in proxy_buyers:
        # Create finalizer contract
        amount = Decimal(amount)

        # Dummy presale min and max arguments
        args = [
            deploy_address,
            proxy_buyer_freeze_ends_at,
            1,  # 1 wei,
            to_wei(10000, "ether"),
            to_wei(10000, "ether"),
        ]
        proxy_buyer, hash = chain.provider.deploy_contract('PreICOProxyBuyer', deploy_args=args)

        # Load presale contract with money
        assert proxy_buyer.call().getState() == 1
        proxy_buyer.transact({"value": to_wei(amount, "ether"), "from": investor}).buy()

        # Set ICO
        proxy_buyer.transact({"from": deploy_address}).setCrowdsale(crowdsale.address)

        # Set proxy buyer contract special price
        pricing_strategy.transact({"from": deploy_address}).setPreicoAddress(proxy_buyer.address, to_wei(price, "ether"))

        # Allow proxy buyer to move money in early
        crowdsale.transact({"from": deploy_address}).setEarlyParicipantWhitelist(proxy_buyer.address, True)

        results.append(proxy_buyer)

    return results
def test_refund(failed_ico_ready_to_refund: Contract, web3: Web3, customer: str, customer_2: str):
    """Customers can claim their refunds."""

    assert failed_ico_ready_to_refund.call().loadedRefund() == to_wei(120, "ether")
    assert failed_ico_ready_to_refund.call().getState() == CrowdsaleState.Refunding

    # Check that the customer gets money back
    invested_amount = failed_ico_ready_to_refund.call().investedAmountOf(customer)
    begin_balance = web3.eth.getBalance(customer)
    failed_ico_ready_to_refund.transact({"from": customer}).refund()
    end_balance = web3.eth.getBalance(customer)

    eth = from_wei(end_balance - begin_balance, "ether")  # Decimal('49.999999999999954693')
    assert (end_balance - begin_balance) >= eth - TRANSACTION_COST_ETH_EPSILON

    failed_ico_ready_to_refund.transact({"from": customer_2}).refund()

    # Everything has been refunded
    assert failed_ico_ready_to_refund.call().weiRefunded() == to_wei(120, "ether")
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.")
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.currentProvider)
        # 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.call().weiRaised(), "ether"), "ether")

        print("Getting events")
        events = crowdsale.pastEvents("Invested").get(only_changes=False)

        # 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 load(chain, web3: Web3, address: str, csv_file: str, token: Contract, address_column: str, amount_column: str, vault_address: str):

    decimals = token.call().decimals()
    decimal_multiplier = 10 ** decimals
    transaction = {"from": address}

    TokenVault = chain.contract_factories.TokenVault
    token_vault = TokenVault(address=vault_address)

    # Check that our tokens are the same
    assert token_vault.call().token().lower() == token.address.lower()

    print("Starting to import investor data to ", token_vault.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()
    total = 0
    for row in rows:
        addr = row[address_column].strip()
        amount = row[amount_column].strip()
        if addr in uniq_addresses:
            raise RuntimeError("Address appears twice in input data", addr)
        uniq_addresses.add(addr)
        amount = Decimal(amount)
        total += amount
        if amount <= 0:
            raise RuntimeError("Invalid amount:".format(amount))

    if token_vault.call().tokensToBeAllocated() != total * decimal_multiplier:
        raise RuntimeError("Expected total amount {}, CSV sum is {}".format(token_vault.call().tokensToBeAllocated(), total))

    # 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(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

        # 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, "vault", token_vault.address, "time passed", time.time() - start_time, "ETH spent", spent)

        if token_vault.call().balances(addr) > 0:
            print("Already issued, skipping")
            continue

        txid = token_vault.transact(transaction).setInvestor(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")
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.")
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(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.call().token())

        decimals = token.call().decimals()
        decimal_multiplier = 10**decimals

        print("We have", decimals, "decimals, multiplier is", decimal_multiplier)

        print("Total amount raised is", from_wei(crowdsale.call().weiRaised(), "ether"), "ether")

        print("Getting events")
        events = crowdsale.pastEvents("Invested").get(only_changes=False)

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