Example #1
0
def get_top_holders(address: str) -> List:
    address = to_address(address)
    if address not in _token_holders:
        holders = requests.get(
            f"https://api.ethplorer.io/getTopTokenHolders/{address}",
            params={
                "apiKey": _ethplorer_api_key,
                "limit": "50"
            },
        ).json()
        if "error" in holders:
            api_key_message = ""
            if _ethplorer_api_key == "freekey":
                api_key_message = (
                    " Adding $ETHPLORER_API_KEY (from https://ethplorer.io) as environment variable"
                    " may solve the problem.")
            raise BrownieTokensError(
                f"Ethplorer returned error: {holders['error']}." +
                api_key_message)

        _token_holders[address] = [
            to_address(i["address"]) for i in holders["holders"]
        ]
        if address in _token_holders[address]:
            # don't steal from the treasury - that could cause wierdness
            _token_holders[address].remove(address)
        update_skipped_addresses(address)

    return _token_holders[address]
Example #2
0
def simulate():
    # fetch the top holders so we can pass the vote
    data = requests.get(
        f"https://api.ethplorer.io/getTopTokenHolders/{TARGET['token']}",
        params={
            "apiKey": "freekey",
            "limit": 50
        },
    ).json()["holders"][::-1]

    # create a list of top holders that will be sufficient to make quorum
    holders = []
    weight = 0
    while weight < TARGET["quorum"] + 5:
        row = data.pop()
        holders.append(to_address(row["address"]))
        weight += row["share"]

    # make the new vote
    top_holder = holders[0]
    vote_id = make_vote(top_holder)

    # vote
    aragon = Contract(TARGET["voting"])
    for acct in holders:
        aragon.vote(vote_id, True, False, {"from": acct})

    # sleep for a week so it has time to pass
    chain.sleep(86400 * 7)

    # moment of truth - execute the vote!
    aragon.executeVote(vote_id, {"from": top_holder})
Example #3
0
def simulate():
    voting_escrow = Contract("0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2")
    aragon = Contract("0xe478de485ad2fe566d49342cbd03e49ed7db3356")

    # make the new vote
    vote_id = make_vote()

    # fetch the top veCRV holders so we can pass the vote
    data = requests.get(
        f"https://api.ethplorer.io/getTopTokenHolders/{voting_escrow}",
        params={
            'apiKey': "freekey",
            'limit': 50
        },
    ).json()['holders'][::-1]

    # vote needs 30% to reach qurom, we'll vote with 35% in case
    # there's been some decay since ethplorer pulled their data
    holders = []
    weight = 0
    while weight < 35:
        row = data.pop()
        holders.append(to_address(row['address']))
        weight += row['share']

    # vote
    for acct in holders:
        aragon.vote(vote_id, True, False, {'from': acct})

    # sleep for a week so it has time to pass
    chain.sleep(86400 * 7)

    # moment of truth - execute the vote!
    aragon.executeVote(vote_id, {'from': holders[0]})
Example #4
0
 def __eq__(self, other):
     if type(other) is str:
         try:
             address = to_address(other)
             return address == self.address
         except ValueError:
             return False
     return super().__eq__(other)
Example #5
0
 def __eq__(self, other):
     if isinstance(other, str):
         try:
             address = to_address(other)
             return address == self.address
         except ValueError:
             return False
     return super().__eq__(other)
def get_balances_for_position_in_accounts_dot_balances(accounts, pos):
    # sl = sublist
    return {
        to_address(balance['account']['address']): balance['shares']
        for sl in [x['balances'] for x in accounts if 0 < len(x['balances'])]
        for balance in sl
        if balance['position'] == str(pos)
    }
Example #7
0
    def remove(self, address):
        '''Removes an account instance from the container.

        Args:
            address: Account instance or address string of account to remove.'''
        address = to_address(address)
        try:
            self._accounts.remove(address)
        except ValueError:
            raise UnknownAccount(f"No account exists for {address}")
Example #8
0
 def __eq__(self, other):
     if isinstance(other, str):
         try:
             address = to_address(other)
             return address == self.address
         except ValueError:
             return False
     if isinstance(other, PublicKeyAccount):
         return other.address == self.address
     return super().__eq__(other)
Example #9
0
 def __eq__(self, other):
     if type(other) is Contract:
         return self.address == other.address and self.bytecode == other.bytecode
     if type(other) is str:
         try:
             address = to_address(other)
             return address == self.address
         except ValueError:
             return False
     return super().__eq__(other)
Example #10
0
 def __eq__(self, other):
     if isinstance(other, _DeployedContractBase):
         return self.address == other.address and self.bytecode == other.bytecode
     if isinstance(other, str):
         try:
             address = to_address(other)
             return address == self.address
         except ValueError:
             return False
     return super().__eq__(other)
Example #11
0
    def transfer(
        self,
        to: "Accounts" = None,
        amount: int = 0,
        gas_limit: Optional[int] = None,
        gas_price: Optional[int] = None,
        data: str = None,
        silent: bool = False,
    ) -> "TransactionReceipt":
        """
        Broadcast a transaction from this account.

        Kwargs:
            to: Account instance or address string to transfer to.
            amount: Amount of ether to send, in wei.
            gas_limit: Gas limit of the transaction.
            gas_price: Gas price of the transaction.
            data: Hexstring of data to include in transaction.
            silent: Toggles console verbosity.

        Returns:
            TransactionReceipt object
        """

        tx = {
            "from":
            self.address,
            "value":
            Wei(amount),
            "nonce":
            self.nonce,
            "gasPrice":
            Wei(gas_price) if gas_price is not None else self._gas_price(),
            "gas":
            Wei(gas_limit) or self._gas_limit(to, amount, data),
            "data":
            HexBytes(data or ""),
        }
        if to:
            tx["to"] = to_address(str(to))
        try:
            txid = self._transact(tx)  # type: ignore
            revert_data = None
        except ValueError as e:
            txid, revert_data = _raise_or_return_tx(e)

        if rpc.is_active():
            rpc._add_to_undo_buffer(self.transfer,
                                    (to, amount, gas_limit, gas_price, data),
                                    {})

        return TransactionReceipt(txid,
                                  self,
                                  silent=silent,
                                  revert_data=revert_data)
Example #12
0
def test_wrong_length():
    with pytest.raises(ValueError):
        to_address("0x00")
    with pytest.raises(ValueError):
        to_address(addr[:20])
    with pytest.raises(ValueError):
        to_address(addr + "00")
Example #13
0
    def estimate_gas(self,
                     to: "Account" = None,
                     amount: int = 0,
                     gas_price: int = None,
                     data: str = None) -> int:
        """
        Estimate the gas cost for a transaction.

        Raises VirtualMachineError if the transaction would revert.

        Arguments
        ---------
        to : Account, optional
            Account instance or address string of transaction recipient.
        amount : int, optional
            Amount of ether to send in wei.
        gas_price : int, optional
            Gas price of the transaction.
        data : str, optional
            Transaction data hexstring.

        Returns
        -------
        Estimated gas value in wei.
        """
        tx: Dict = {
            "from": self.address,
            "to": to_address(str(to)) if to else None,
            "value": Wei(amount),
            "data": HexBytes(data or ""),
        }
        if gas_price is not None:
            tx["gasPrice"] = gas_price
        try:
            return web3.eth.estimate_gas(tx)
        except ValueError as exc:
            revert_gas_limit = CONFIG.active_network["settings"][
                "reverting_tx_gas_limit"]
            if revert_gas_limit == "max":
                revert_gas_limit = web3.eth.get_block("latest")["gasLimit"]
                CONFIG.active_network["settings"][
                    "reverting_tx_gas_limit"] = revert_gas_limit
            if revert_gas_limit:
                return revert_gas_limit

            msg = exc.args[0]["message"] if isinstance(exc.args[0],
                                                       dict) else str(exc)
            raise ValueError(
                f"Gas estimation failed: '{msg}'. This transaction will likely revert. "
                "If you wish to broadcast, you must set the gas limit manually."
            )
Example #14
0
def _resolve_address(address: str) -> str:
    if not isinstance(address, str) or "." not in address:
        return to_address(address)
    address = address.lower()
    if address not in _ens_cache:
        try:
            ns = ENS.fromWeb3(web3._mainnet)
        except MainnetUndefined as e:
            raise MainnetUndefined(
                f"Cannot resolve ENS address - {e}") from None
        resolved_address = ns.address(address)
        _ens_cache[address] = resolved_address
    if _ens_cache[address] is None:
        raise UnsetENSName(f"ENS address '{address}' is not set")
    return _ens_cache[address]
def test_alice_and_bob_exist():
    gql = """
        query {
            accounts {
                id
            }
        }
    """

    result = query(gql)

    accounts = [to_address(x['id']) for x in result['accounts']]

    assert ENV("ALICE") in accounts, "Alice is not in returned accounts"
    assert ENV("BOB") in accounts, "Bob is not in returned accounts"
Example #16
0
    def at(self, address):
        '''Retrieves an Account instance from the address string. Raises
        ValueError if the account cannot be found.

        Args:
            address: string of the account address.

        Returns:
            Account instance.
        '''
        address = to_address(address)
        try:
            return next(i for i in self._accounts if i == address)
        except StopIteration:
            raise UnknownAccount(f"No account exists for {address}")
Example #17
0
def swap(
    alice,
    base_pool,
    factory,
    plain_implementations,
    meta_implementation_idx,
    coins,
    project,
    plain_pool_size,
    pool_type,
    is_meta_pool,
    web3,
):
    if not is_meta_pool:
        # modifies the factory so should be module scoped
        tx = factory.deploy_plain_pool(
            "Test Plain Pool",
            "TPP",
            coins + [ZERO_ADDRESS] * (4 - plain_pool_size),
            200,
            4000000,
            0,
            pool_type,
            {"from": alice},
        )
        return getattr(project, plain_implementations[pool_type]._name).at(
            tx.return_value)
    else:
        if factory.pool_count() != 0:
            return state._find_contract(factory.pool_list(0))

        tx = factory.deploy_metapool(
            base_pool,
            "Test Meta Pool",
            "TMP",
            coins[0],
            200,
            4000000,
            meta_implementation_idx,
            {"from": alice},
        )
        key = convert.to_address(
            HexBytes(web3.eth.get_code(tx.return_value))[10:30].hex())
        instance = Contract.from_abi("Meta Instance", tx.return_value,
                                     meta_contracts[key])
        instance._build["language"] = "Vyper"
        state._add_contract(instance)
        return instance
    def __init__(self, address):
        super().__init__(address)

        # get top token holder addresses
        address = self.address
        if address not in _holders:
            holders = requests.get(
                f"https://api.ethplorer.io/getTopTokenHolders/{address}",
                params={
                    'apiKey': "freekey",
                    'limit': 50
                },
            ).json()
            _holders[address] = [
                to_address(i['address']) for i in holders['holders']
            ]
Example #19
0
def _resolve_address(domain: str) -> str:
    # convert ENS domain to address
    if not isinstance(domain, str) or "." not in domain:
        return to_address(domain)
    domain = domain.lower()
    if domain not in _ens_cache or time.time() - _ens_cache[domain][1] > 86400:
        try:
            ns = ENS.fromWeb3(web3._mainnet)
        except MainnetUndefined as e:
            raise MainnetUndefined(f"Cannot resolve ENS address - {e}") from None
        address = ns.address(domain)
        _ens_cache[domain] = [address, int(time.time())]
        with _get_path().open("w") as fp:
            json.dump(_ens_cache, fp)
    if _ens_cache[domain][0] is None:
        raise UnsetENSName(f"ENS domain '{domain}' is not set")
    return _ens_cache[domain][0]
Example #20
0
    def __init__(self, address, pool_data):
        super().__init__(address)

        # standardize mint / rate methods
        if 'wrapped_contract' in pool_data:
            fn_names = WRAPPED_COIN_METHODS[pool_data['wrapped_contract']]
            for target, attr in fn_names.items():
                if hasattr(self, attr):
                    setattr(self, target, getattr(self, attr))

        # get top token holder addresses
        address = self.address
        if address not in _holders:
            holders = requests.get(
                f"https://api.ethplorer.io/getTopTokenHolders/{address}",
                params={'apiKey': "freekey", 'limit': 50},
            ).json()
            _holders[address] = [to_address(i['address']) for i in holders['holders']]
Example #21
0
    def __init__(self, address, pool_data=None):
        super().__init__(address)

        # standardize mint / rate methods
        if pool_data is not None and "wrapped_contract" in pool_data:
            fn_names = WRAPPED_COIN_METHODS[pool_data["wrapped_contract"]]
            for target, attr in fn_names.items():
                if hasattr(self, attr) and target != attr:
                    setattr(self, target, getattr(self, attr))

        # get top token holder addresses
        address = self.address
        if address not in _holders:
            holders = requests.get(
                f"https://api.ethplorer.io/getTopTokenHolders/{address}",
                params={"apiKey": "freekey", "limit": 50},
            ).json()
            _holders[address] = [to_address(i["address"]) for i in holders["holders"]]
def main():
    voting_escrow = Contract("0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2")
    aragon = Contract("0xe478de485ad2fe566d49342cbd03e49ed7db3356")
    agent = Contract("0x40907540d8a6c65c637785e8f8b742ae6b0b9968")

    # fetch the top veCRV holders so we can pass the vote
    data = requests.get(
        f"https://api.ethplorer.io/getTopTokenHolders/{voting_escrow}",
        params={
            'apiKey': "freekey",
            'limit': 50
        },
    ).json()['holders'][::-1]

    # vote needs 30% to reach qurom, we'll vote with 35% in case
    # there's been some decay since ethplorer pulled their data
    holders = []
    weight = 0
    while weight < 35:
        row = data.pop()
        holders.append(to_address(row['address']))
        weight += row['share']

    # prepare the evm calldata for the vote
    agent_calldata = agent.execute.encode_input(TARGET, 0, CALLDATA)[2:]
    length = hex(len(agent_calldata) // 2)[2:].zfill(8)
    evm_script = f"0x0000000140907540d8a6c65c637785e8f8b742ae6b0b9968{length}{agent_calldata}"

    # create the new vote
    tx = aragon.newVote(evm_script, DESCRIPTION, False, False,
                        {'from': holders[0]})
    vote_id = tx.events['StartVote']['voteId']

    # vote
    for acct in holders:
        aragon.vote(vote_id, True, False, {'from': acct})

    # sleep for a week so it has time to pass
    chain.sleep(86400 * 7)

    # moment of truth - execute the vote!
    aragon.executeVote(vote_id, {'from': holders[0]})

    print(f"Success!\n\nEVM script for vote: {evm_script}")
Example #23
0
    def connect_to_clef(self, uri: str = None, timeout: int = 120) -> None:
        """
        Connect to Clef and import open accounts.

        Clef is an account signing utility packaged with Geth, which can be
        used to interact with HW wallets in Brownie. Before calling this
        function, Clef must be running in another command prompt.

        Arguments
        ---------
        uri : str
            IPC path or http url to use to connect to clef. If None is given,
            uses the default IPC path on Unix systems or localhost on Windows.
        timeout : int
            The number of seconds to wait on a clef request before raising a
            timeout exception.
        """
        provider = None
        if uri is None:
            if sys.platform == "win32":
                uri = "http://localhost:8550/"
            else:
                uri = Path.home().joinpath(".clef/clef.ipc").as_posix()
        try:
            if Path(uri).exists():
                provider = IPCProvider(uri, timeout=timeout)
        except OSError:
            if uri is not None and uri.startswith("http"):
                provider = HTTPProvider(uri, {"timeout": timeout})
        if provider is None:
            raise ValueError(
                "Unknown URI, must be IPC socket path or URL starting with 'http'"
            )

        response = provider.make_request("account_list", [])
        if "error" in response:
            raise ValueError(response["error"]["message"])

        for address in response["result"]:
            if to_address(address) not in self._accounts:
                self._accounts.append(ClefAccount(address, provider))
Example #24
0
    def at(self, address, owner=None, tx=None):
        '''Returns a contract address.

        Raises ValueError if no bytecode exists at the address.

        Args:
            address: Address string of the contract.
            owner: Default Account instance to send contract transactions from.
            tx: Transaction ID of the contract creation.'''
        address = to_address(address)
        contract = _contracts.find(address)
        if contract:
            if contract._name == self._name:
                return contract
            raise ValueError(
                f"Contract '{contract._name}' already declared at {address}")
        if web3.eth.getCode(address).hex() == "0x":
            raise ValueError(f"No contract deployed at {address}")
        contract = Contract(address, self._build, owner, tx)
        _contracts.add(contract)
        return contract
Example #25
0
 def __init__(self, address, owner=None, tx=None):
     address = to_address(address)
     self.bytecode = web3.eth.getCode(address).hex()[2:]
     if not self.bytecode:
         raise ContractNotFound(f"No contract deployed at {address}")
     self._owner = owner
     self.tx = tx
     self.address = address
     fn_names = [i['name'] for i in self.abi if i['type'] == "function"]
     for abi in [i for i in self.abi if i['type'] == "function"]:
         name = f"{self._name}.{abi['name']}"
         if fn_names.count(abi['name']) == 1:
             self._check_and_set(
                 abi['name'], _get_method_object(address, abi, name, owner))
             continue
         if not hasattr(self, abi['name']):
             self._check_and_set(abi['name'],
                                 OverloadedMethod(address, name, owner))
         key = ",".join(i['type'] for i in abi['inputs']).replace('256', '')
         getattr(self, abi['name']).methods[key] = _get_method_object(
             address, abi, name, owner)
Example #26
0
def crypto_pool(
    alice,
    crypto_project,
    crypto_math,
    crypto_lp_token,
    crypto_views,
    crypto_coins,
    crypto_initial_prices,
):
    # taken from curvefi/curve-crypto-contract
    keys = [0, 1, 2, 16, 17, 18, "1,#0", "1,#1", "1,#2"]
    values = (
        [crypto_math.address, crypto_lp_token.address, crypto_views.address]
        + [coin.address for coin in crypto_coins]
        + [f"{10 ** (18 - coin.decimals())}," for coin in crypto_coins]
    )
    source = crypto_project.CurveCryptoSwap._build["source"]
    for k, v in zip(keys, values):
        if isinstance(k, int):
            k = convert.to_address(convert.to_bytes(k, "bytes20"))
        source.replace(k, v)

    CryptoPool = compile_source(source, vyper_version="0.2.12").Vyper
    swap = CryptoPool.deploy(
        alice,
        135 * 3 ** 3,  # A
        int(7e-5 * 1e18),  # gamma
        int(4e-4 * 1e10),  # mid_fee
        int(4e-3 * 1e10),  # out_fee
        int(0.0028 * 1e18),  # price_threshold
        int(0.01 * 1e18),  # fee_gamma
        int(0.0015 * 1e18),  # adjustment_step
        0,  # admin_fee
        600,  # ma_half_time
        crypto_initial_prices,
        {"from": alice},
    )
    crypto_lp_token.set_minter(swap, {"from": alice})
    return swap
Example #27
0
    def transfer(
        self,
        to: "Accounts",
        amount: int,
        gas_limit: int = None,
        gas_price: int = None,
        data: str = "",
    ) -> "TransactionReceipt":
        """Transfers ether from this account.

        Args:
            to: Account instance or address string to transfer to.
            amount: Amount of ether to send, in wei.

        Kwargs:
            gas_limit: Gas limit of the transaction.
            gas_price: Gas price of the transaction.
            data: Hexstring of data to include in transaction.

        Returns:
            TransactionReceipt object"""

        try:
            txid = self._transact(  # type: ignore
                {
                    "from": self.address,
                    "to": to_address(str(to)),
                    "value": Wei(amount),
                    "nonce": self.nonce,
                    "gasPrice": Wei(gas_price) if gas_price is not None else self._gas_price(),
                    "gas": Wei(gas_limit) or self._gas_limit(to, amount, data),
                    "data": HexBytes(data),
                }
            )
            revert_data = None
        except ValueError as e:
            txid, revert_data = _raise_or_return_tx(e)
        return TransactionReceipt(txid, self, revert_data=revert_data)
Example #28
0
    def __init__(self, coin_data, is_wrapped):
        self._coin_data = coin_data

        wrapped_address = coin_data.get("wrapped_address")
        underlying_address = coin_data.get("underlying_address")
        if is_wrapped:
            address = wrapped_address or underlying_address
        else:
            address = underlying_address or wrapped_address
        super().__init__(address)

        if is_wrapped and wrapped_address:
            self._rate_fn = next(
                getattr(self, i) for i in self._rate_methods
                if hasattr(self, i))
        else:
            if "base_pool_token" in coin_data:
                base_pool = next(i for i in _pooldata.values()
                                 if i.get("lp_token_address") == self.address)
                self._rate_fn = Contract(
                    base_pool["swap_address"]).get_virtual_price
            else:
                self._rate_fn = None

        # get top token holder addresses
        address = self.address
        if address not in _holders:
            holders = requests.get(
                f"https://api.ethplorer.io/getTopTokenHolders/{address}",
                params={
                    'apiKey': "freekey",
                    'limit': 50
                },
            ).json()
            _holders[address] = [
                to_address(i['address']) for i in holders['holders']
            ]
Example #29
0
 def __contains__(self, address: str) -> bool:
     try:
         address = to_address(address)
         return address in self._accounts
     except ValueError:
         return False
Example #30
0
    def transfer(
        self,
        to: "Account" = None,
        amount: int = 0,
        gas_limit: Optional[int] = None,
        gas_buffer: Optional[float] = None,
        gas_price: Optional[int] = None,
        data: str = None,
        nonce: Optional[int] = None,
        required_confs: int = 1,
        allow_revert: bool = None,
        silent: bool = None,
    ) -> TransactionReceipt:
        """
        Broadcast a transaction from this account.

        Kwargs:
            to: Account instance or address string to transfer to.
            amount: Amount of ether to send, in wei.
            gas_limit: Gas limit of the transaction.
            gas_buffer: Multiplier to apply to gas limit.
            gas_price: Gas price of the transaction.
            nonce: Nonce to use for the transaction.
            data: Hexstring of data to include in transaction.
            silent: Toggles console verbosity.

        Returns:
            TransactionReceipt object
        """
        if gas_limit and gas_buffer:
            raise ValueError("Cannot set gas_limit and gas_buffer together")
        if silent is None:
            silent = bool(CONFIG.mode == "test" or CONFIG.argv["silent"])
        with self._lock:
            gas_price, gas_strategy, gas_iter = self._gas_price(gas_price)
            gas_limit = Wei(gas_limit) or self._gas_limit(
                to, amount, gas_price, gas_buffer, data)
            tx = {
                "from": self.address,
                "value": Wei(amount),
                "nonce": nonce if nonce is not None else self._pending_nonce(),
                "gasPrice": gas_price,
                "gas": gas_limit,
                "data": HexBytes(data or ""),
            }
            if to:
                tx["to"] = to_address(str(to))
            try:
                txid = self._transact(tx, allow_revert)  # type: ignore
                exc, revert_data = None, None
            except ValueError as e:
                exc = VirtualMachineError(e)
                if not hasattr(exc, "txid"):
                    raise exc from None
                txid = exc.txid
                revert_data = (exc.revert_msg, exc.pc, exc.revert_type)

            receipt = TransactionReceipt(
                txid,
                self,
                required_confs=required_confs,
                is_blocking=False,
                silent=silent,
                revert_data=revert_data,
            )

        receipt = self._await_confirmation(receipt, required_confs,
                                           gas_strategy, gas_iter)

        if rpc.is_active():
            undo_thread = threading.Thread(
                target=Chain()._add_to_undo_buffer,
                args=(
                    receipt,
                    self.transfer,
                    (to, amount, gas_limit, gas_buffer, gas_price, data, None),
                    {},
                ),
                daemon=True,
            )
            undo_thread.start()

        receipt._raise_if_reverted(exc)
        return receipt