예제 #1
0
    def __init__(self, w3: Web3, rootchain_address: AnyAddress,
                 private_key: bytes):
        self._w3 = w3
        self._rootchain = self._w3.eth.contract(rootchain_address,
                                                **rootchain_interface)
        self._acct = Account.from_key(private_key)
        # Allow web3 to autosign with account
        middleware = construct_sign_and_send_raw_middleware(private_key)
        self._w3.middleware_onion.add(middleware)
        # Set up dats structures
        self.pending_deposits = {
        }  # Dict mapping tokenId to deposit txn in Rootchain contract
        self.deposits = {}  # Dict mapping tokenId to last known txn
        self.transactions = [TokenToTxnHashIdSMT()
                             ]  # Ordered list of block txn dbs
        self.last_sync_time = self._w3.eth.blockNumber

        # Add listeners (dict of filters: callbacks)
        self.listeners = {}
        # Add listener for deposits
        self.listeners[self._rootchain.events.DepositAdded.createFilter(
            fromBlock=self._w3.eth.blockNumber)] = self.addDeposit
        # Add listener for deposit cancellations
        self.listeners[self._rootchain.events.DepositCancelled.createFilter(
            fromBlock=self._w3.eth.blockNumber, )] = self.remDeposit

        # Add listener for challenging withdrawals
        self.listeners[self._rootchain.events.ExitStarted.createFilter(
            fromBlock=self._w3.eth.blockNumber, )] = self.checkExit

        # Add listener for finalized withdrawals
        self.listeners[self._rootchain.events.ExitFinished.createFilter(
            fromBlock=self._w3.eth.blockNumber, )] = self.remDeposit
예제 #2
0
def configure_default_account(w3: Web3, private_key: str) -> HexAddress:
    """Sets default account for interacting with smart contracts."""
    account = w3.eth.account.from_key(private_key)
    w3.middleware_onion.add(construct_sign_and_send_raw_middleware(account))
    logger.warning(
        "Injected middleware for capturing transactions and sending as raw")

    w3.eth.defaultAccount = account.address
    logger.info(f"Configured default account {w3.eth.defaultAccount}")

    return account.address
예제 #3
0
def _keyfile_middleware(keyfile_path):
    import json
    with open(keyfile_path, 'r') as f:
        keyfile = json.loads(f.read())

    from getpass import getpass
    password = getpass("Please Input Keyfile Password: ")

    from eth_account import Account
    privateKey = Account.decrypt(keyfile, password)
    account = Account.privateKeyToAccount(privateKey)

    from web3.middleware.signing import construct_sign_and_send_raw_middleware
    middleware = construct_sign_and_send_raw_middleware(privateKey)
    return account, middleware
예제 #4
0
파일: utils.py 프로젝트: selendra/sto
def deploy_contract_on_eth_network(web3, abi, bytecode, bytecode_runtime,
                                   private_key, ethereum_gas_limit,
                                   ethereum_gas_price, constructor_args):
    from web3.middleware.signing import construct_sign_and_send_raw_middleware
    # the following code helps deploying using infura
    web3.middleware_stack.add(
        construct_sign_and_send_raw_middleware(private_key))

    contract = web3.eth.contract(abi=abi,
                                 bytecode=bytecode,
                                 bytecode_runtime=bytecode_runtime)
    tx_kwargs = {'from': priv_key_to_address(private_key)}
    if ethereum_gas_limit:
        tx_kwargs['gas'] = ethereum_gas_limit
    if ethereum_gas_price:
        tx_kwargs['gasPrice'] = ethereum_gas_price

    tx_hash = contract.constructor(*constructor_args).transact(tx_kwargs)
    receipt = web3.eth.waitForTransactionReceipt(tx_hash)
    assert receipt['status'] == 1, "failed to deploy contract"
    return receipt['contractAddress']
예제 #5
0
 def __init__(self,
              w3: Web3,
              token_address: AnyAddress,
              rootchain_address: AnyAddress,
              operator: Operator,
              private_key: bytes,
              purse: Set[Token] = None):
     self._w3 = w3
     self._token = self._w3.eth.contract(token_address, **token_interface)
     self._rootchain = self._w3.eth.contract(rootchain_address,
                                             **rootchain_interface)
     self._operator = operator
     self._acct = Account.from_key(private_key)
     # Allow web3 to autosign with account
     middleware = construct_sign_and_send_raw_middleware(private_key)
     self._w3.middleware_onion.add(middleware)
     # Load Tokens
     self.purse = purse if purse else []
     # Add listeners (dict of filters: callbacks)
     self.listeners = {}
     # Add listener to accept list of deposited tokens
     self.tokens_in_deposit = []
     self.listeners[self._rootchain.events.BlockPublished.createFilter(
         fromBlock=self._w3.eth.blockNumber)] = self.handleDeposits
def main(chain, address, token, csv_file, limit, start_from, issuer_address,
         address_column, amount_column, allow_zero, master_address, gas_price,
         solc_version, private_key):
    """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

        if private_key:
            web3.middleware_stack.add(
                construct_sign_and_send_raw_middleware(private_key))

        print("Web3 provider is", web3.providers[0])
        print("Deployer account address is", address)
        print("Deployer account balance is",
              from_wei(web3.eth.getBalance(address), "ether"), "ETH")

        # Goes through geth account unlock process if needed
        if is_account_locked(web3, address):
            request_account_unlock(c, address, timeout=3600 * 6)
            assert not is_account_locked(web3, address)

        Token = c.provider.get_base_contract_factory('CentrallyIssuedToken')
        token = Token(address=token)

        print("Token is", token.address)
        print("Total supply is", token.functions.totalSupply().call())
        print("Upgrade master is", token.functions.upgradeMaster().call())
        print("Deployer account token balance is",
              token.functions.balanceOf(address).call())

        decimals = token.functions.decimals().call()
        print("Token decimal places is", decimals)
        assert decimals >= 0

        decimal_multiplier = 10**decimals

        if gas_price:
            gas_price = int(gas_price) * 10**9
        else:
            gas_price = web3.eth.gasPrice * 2

        transaction = {"from": address, "gasPrice": gas_price}

        print("Using gas price of", gas_price / 10**9, "GWei")

        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,
                  "transaction parameters", transaction)
            issuer, txhash = c.provider.deploy_contract(
                "Issuer", 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 = "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,
                compiler=solc_version)
            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.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]

        # 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": gas_price,
                "gas": 200000,  # Use 100k limit
            }

            tokens = int(tokens)

            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(addr).call():
                print("Already issued, skipping")
                continue

            txid = issuer.functions.issue(addr, tokens).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.")
예제 #7
0
def add_signing_middleware(w3: Web3, account: Account):
    _middleware = construct_sign_and_send_raw_middleware(account.privateKey)
    # TODO Change to "middleware_onion" after upgrade to web3>5.0.0a3
    w3.middleware_stack.add(_middleware)