#!/usr/bin/python3

import sys
from typing import Optional, Type

import eth_abi
import psutil
import yaml
from hexbytes import HexBytes

import brownie

# network

ERROR_SIG = "0x08c379a0"


class UnknownAccount(Exception):
    pass


class UndeployedLibrary(Exception):
    pass


class UnsetENSName(Exception):
    pass


class IncompatibleEVMVersion(Exception):
    pass


class RPCProcessError(Exception):
    def __init__(self, cmd: str, uri: str) -> None:
        super().__init__(f"Unable to launch local RPC client.\nCommand: {cmd}\nURI: {uri}")


class RPCConnectionError(Exception):
    def __init__(self, cmd: str, proc: psutil.Popen, uri: str) -> None:
        msg = (
            "Able to launch RPC client, but unable to connect."
            f"\n\nCommand: {cmd}\nURI: {uri}\nExit Code: {proc.poll()}"
        )
        if sys.platform != "win32":
            out = proc.stdout.read().decode().strip() or "  (Empty)"
            err = proc.stderr.read().decode().strip() or "  (Empty)"
            msg = f"{msg}\n\nStdout:\n{out}\n\nStderr:\n{err}"
        super().__init__(msg)


class RPCRequestError(Exception):
    pass


class MainnetUndefined(Exception):
    pass


class VirtualMachineError(Exception):

    """
    Raised when a call to a contract causes an EVM exception.

    Attributes
    ----------
    message : str
        The full error message received from the RPC client.
    revert_msg : str
        The returned error string, if any.
    revert_type : str
        The error type.
    pc : int
        The program counter where the error was raised.
    txid : str
        The transaction ID that raised the error.
    """

    def __init__(self, exc: ValueError) -> None:
        self.txid: str = ""
        self.source: str = ""
        self.revert_type: str = ""
        self.pc: Optional[int] = None
        self.revert_msg: Optional[str] = None
        self.dev_revert_msg: Optional[str] = None

        try:
            exc = exc.args[0]
        except Exception:
            pass

        if not (isinstance(exc, dict) and "message" in exc):
            raise ValueError(str(exc)) from None

        if "data" not in exc:
            raise ValueError(exc["message"]) from None

        self.message: str = exc["message"].rstrip(".")

        if isinstance(exc["data"], str):
            # handle parity exceptions - this logic probably is not perfect
            if not exc["data"].startswith(ERROR_SIG):
                err_msg = exc["data"]
                if err_msg.endswith("0x"):
                    err_msg = exc["data"][:-2].strip()
                raise ValueError(f"{self.message}: {err_msg}") from None

            self.revert_type = "revert"
            err_msg = exc["data"][len(ERROR_SIG) :]
            (err_msg,) = eth_abi.decode(["string"], HexBytes(err_msg))
            self.revert_msg = err_msg

            return

        try:
            txid, data = next((k, v) for k, v in exc["data"].items() if k.startswith("0x"))
            self.revert_type = data["error"]
        except StopIteration:
            raise ValueError(exc["message"]) from None

        self.txid = txid
        self.source = ""
        self.pc = data.get("program_counter")
        if self.pc and self.revert_type == "revert":
            self.pc -= 1

        self.revert_msg = data.get("reason")
        self.dev_revert_msg = brownie.project.build._get_dev_revert(self.pc)
        if self.revert_msg is None and self.revert_type in ("revert", "invalid opcode"):
            self.revert_msg = self.dev_revert_msg
        elif self.revert_msg == "Failed assertion":
            self.revert_msg = self.dev_revert_msg or self.revert_msg

    def __str__(self) -> str:
        if not hasattr(self, "revert_type"):
            return str(self.message)
        msg = self.revert_type
        if self.revert_msg:
            msg = f"{msg}: {self.revert_msg}"
        if self.source:
            msg = f"{msg}\n{self.source}"
        return str(msg)

    def _with_attr(self, **kwargs) -> "VirtualMachineError":
        for key, value in kwargs.items():
            setattr(self, key, value)
        if self.revert_msg == "Failed assertion":
            self.revert_msg = self.dev_revert_msg or self.revert_msg  # type: ignore
        return self


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


# project/


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):
    def __init__(self, e: Type[psutil.Popen], compiler: str = "Compiler") -> None:
        self.compiler = compiler

        err_json = yaml.safe_load(e.stdout_data)
        err = [i.get("formattedMessage") or i["message"] for i in err_json["errors"]]
        super().__init__(f"{compiler} returned the following errors:\n\n" + "\n".join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass

a772324b98787eedf684a527339b6b873a76ff8e
<mask token>


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):

    def __init__(self, e: Type[psutil.Popen], compiler: str='Compiler') ->None:
        self.compiler = compiler
        err_json = yaml.safe_load(e.stdout_data)
        err = [(i.get('formattedMessage') or i['message']) for i in
            err_json['errors']]
        super().__init__(f'{compiler} returned the following errors:\n\n' +
            '\n'.join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass

<mask token>


class RPCProcessError(Exception):
    <mask token>


class RPCConnectionError(Exception):

    def __init__(self, cmd: str, proc: psutil.Popen, uri: str) ->None:
        msg = f"""Able to launch RPC client, but unable to connect.

Command: {cmd}
URI: {uri}
Exit Code: {proc.poll()}"""
        if sys.platform != 'win32':
            out = proc.stdout.read().decode().strip() or '  (Empty)'
            err = proc.stderr.read().decode().strip() or '  (Empty)'
            msg = f'{msg}\n\nStdout:\n{out}\n\nStderr:\n{err}'
        super().__init__(msg)


class RPCRequestError(Exception):
    pass


class MainnetUndefined(Exception):
    pass


class VirtualMachineError(Exception):
    """
    Raised when a call to a contract causes an EVM exception.

    Attributes
    ----------
    message : str
        The full error message received from the RPC client.
    revert_msg : str
        The returned error string, if any.
    revert_type : str
        The error type.
    pc : int
        The program counter where the error was raised.
    txid : str
        The transaction ID that raised the error.
    """

    def __init__(self, exc: ValueError) ->None:
        self.txid: str = ''
        self.source: str = ''
        self.revert_type: str = ''
        self.pc: Optional[int] = None
        self.revert_msg: Optional[str] = None
        self.dev_revert_msg: Optional[str] = None
        try:
            exc = exc.args[0]
        except Exception:
            pass
        if not (isinstance(exc, dict) and 'message' in exc):
            raise ValueError(str(exc)) from None
        if 'data' not in exc:
            raise ValueError(exc['message']) from None
        self.message: str = exc['message'].rstrip('.')
        if isinstance(exc['data'], str):
            if not exc['data'].startswith(ERROR_SIG):
                err_msg = exc['data']
                if err_msg.endswith('0x'):
                    err_msg = exc['data'][:-2].strip()
                raise ValueError(f'{self.message}: {err_msg}') from None
            self.revert_type = 'revert'
            err_msg = exc['data'][len(ERROR_SIG):]
            err_msg, = eth_abi.decode(['string'], HexBytes(err_msg))
            self.revert_msg = err_msg
            return
        try:
            txid, data = next((k, v) for k, v in exc['data'].items() if k.
                startswith('0x'))
            self.revert_type = data['error']
        except StopIteration:
            raise ValueError(exc['message']) from None
        self.txid = txid
        self.source = ''
        self.pc = data.get('program_counter')
        if self.pc and self.revert_type == 'revert':
            self.pc -= 1
        self.revert_msg = data.get('reason')
        self.dev_revert_msg = brownie.project.build._get_dev_revert(self.pc)
        if self.revert_msg is None and self.revert_type in ('revert',
            'invalid opcode'):
            self.revert_msg = self.dev_revert_msg
        elif self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg

    def __str__(self) ->str:
        if not hasattr(self, 'revert_type'):
            return str(self.message)
        msg = self.revert_type
        if self.revert_msg:
            msg = f'{msg}: {self.revert_msg}'
        if self.source:
            msg = f'{msg}\n{self.source}'
        return str(msg)

    def _with_attr(self, **kwargs) ->'VirtualMachineError':
        for key, value in kwargs.items():
            setattr(self, key, value)
        if self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg
        return self


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):

    def __init__(self, e: Type[psutil.Popen], compiler: str='Compiler') ->None:
        self.compiler = compiler
        err_json = yaml.safe_load(e.stdout_data)
        err = [(i.get('formattedMessage') or i['message']) for i in
            err_json['errors']]
        super().__init__(f'{compiler} returned the following errors:\n\n' +
            '\n'.join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass

<mask token>


class UnsetENSName(Exception):
    pass


class IncompatibleEVMVersion(Exception):
    pass


class RPCProcessError(Exception):

    def __init__(self, cmd: str, uri: str) ->None:
        super().__init__(
            f'Unable to launch local RPC client.\nCommand: {cmd}\nURI: {uri}')


class RPCConnectionError(Exception):

    def __init__(self, cmd: str, proc: psutil.Popen, uri: str) ->None:
        msg = f"""Able to launch RPC client, but unable to connect.

Command: {cmd}
URI: {uri}
Exit Code: {proc.poll()}"""
        if sys.platform != 'win32':
            out = proc.stdout.read().decode().strip() or '  (Empty)'
            err = proc.stderr.read().decode().strip() or '  (Empty)'
            msg = f'{msg}\n\nStdout:\n{out}\n\nStderr:\n{err}'
        super().__init__(msg)


class RPCRequestError(Exception):
    pass


class MainnetUndefined(Exception):
    pass


class VirtualMachineError(Exception):
    """
    Raised when a call to a contract causes an EVM exception.

    Attributes
    ----------
    message : str
        The full error message received from the RPC client.
    revert_msg : str
        The returned error string, if any.
    revert_type : str
        The error type.
    pc : int
        The program counter where the error was raised.
    txid : str
        The transaction ID that raised the error.
    """

    def __init__(self, exc: ValueError) ->None:
        self.txid: str = ''
        self.source: str = ''
        self.revert_type: str = ''
        self.pc: Optional[int] = None
        self.revert_msg: Optional[str] = None
        self.dev_revert_msg: Optional[str] = None
        try:
            exc = exc.args[0]
        except Exception:
            pass
        if not (isinstance(exc, dict) and 'message' in exc):
            raise ValueError(str(exc)) from None
        if 'data' not in exc:
            raise ValueError(exc['message']) from None
        self.message: str = exc['message'].rstrip('.')
        if isinstance(exc['data'], str):
            if not exc['data'].startswith(ERROR_SIG):
                err_msg = exc['data']
                if err_msg.endswith('0x'):
                    err_msg = exc['data'][:-2].strip()
                raise ValueError(f'{self.message}: {err_msg}') from None
            self.revert_type = 'revert'
            err_msg = exc['data'][len(ERROR_SIG):]
            err_msg, = eth_abi.decode(['string'], HexBytes(err_msg))
            self.revert_msg = err_msg
            return
        try:
            txid, data = next((k, v) for k, v in exc['data'].items() if k.
                startswith('0x'))
            self.revert_type = data['error']
        except StopIteration:
            raise ValueError(exc['message']) from None
        self.txid = txid
        self.source = ''
        self.pc = data.get('program_counter')
        if self.pc and self.revert_type == 'revert':
            self.pc -= 1
        self.revert_msg = data.get('reason')
        self.dev_revert_msg = brownie.project.build._get_dev_revert(self.pc)
        if self.revert_msg is None and self.revert_type in ('revert',
            'invalid opcode'):
            self.revert_msg = self.dev_revert_msg
        elif self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg

    def __str__(self) ->str:
        if not hasattr(self, 'revert_type'):
            return str(self.message)
        msg = self.revert_type
        if self.revert_msg:
            msg = f'{msg}: {self.revert_msg}'
        if self.source:
            msg = f'{msg}\n{self.source}'
        return str(msg)

    def _with_attr(self, **kwargs) ->'VirtualMachineError':
        for key, value in kwargs.items():
            setattr(self, key, value)
        if self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg
        return self


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):

    def __init__(self, e: Type[psutil.Popen], compiler: str='Compiler') ->None:
        self.compiler = compiler
        err_json = yaml.safe_load(e.stdout_data)
        err = [(i.get('formattedMessage') or i['message']) for i in
            err_json['errors']]
        super().__init__(f'{compiler} returned the following errors:\n\n' +
            '\n'.join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass

<mask token>
ERROR_SIG = '0x08c379a0'


class UnknownAccount(Exception):
    pass


class UndeployedLibrary(Exception):
    pass


class UnsetENSName(Exception):
    pass


class IncompatibleEVMVersion(Exception):
    pass


class RPCProcessError(Exception):

    def __init__(self, cmd: str, uri: str) ->None:
        super().__init__(
            f'Unable to launch local RPC client.\nCommand: {cmd}\nURI: {uri}')


class RPCConnectionError(Exception):

    def __init__(self, cmd: str, proc: psutil.Popen, uri: str) ->None:
        msg = f"""Able to launch RPC client, but unable to connect.

Command: {cmd}
URI: {uri}
Exit Code: {proc.poll()}"""
        if sys.platform != 'win32':
            out = proc.stdout.read().decode().strip() or '  (Empty)'
            err = proc.stderr.read().decode().strip() or '  (Empty)'
            msg = f'{msg}\n\nStdout:\n{out}\n\nStderr:\n{err}'
        super().__init__(msg)


class RPCRequestError(Exception):
    pass


class MainnetUndefined(Exception):
    pass


class VirtualMachineError(Exception):
    """
    Raised when a call to a contract causes an EVM exception.

    Attributes
    ----------
    message : str
        The full error message received from the RPC client.
    revert_msg : str
        The returned error string, if any.
    revert_type : str
        The error type.
    pc : int
        The program counter where the error was raised.
    txid : str
        The transaction ID that raised the error.
    """

    def __init__(self, exc: ValueError) ->None:
        self.txid: str = ''
        self.source: str = ''
        self.revert_type: str = ''
        self.pc: Optional[int] = None
        self.revert_msg: Optional[str] = None
        self.dev_revert_msg: Optional[str] = None
        try:
            exc = exc.args[0]
        except Exception:
            pass
        if not (isinstance(exc, dict) and 'message' in exc):
            raise ValueError(str(exc)) from None
        if 'data' not in exc:
            raise ValueError(exc['message']) from None
        self.message: str = exc['message'].rstrip('.')
        if isinstance(exc['data'], str):
            if not exc['data'].startswith(ERROR_SIG):
                err_msg = exc['data']
                if err_msg.endswith('0x'):
                    err_msg = exc['data'][:-2].strip()
                raise ValueError(f'{self.message}: {err_msg}') from None
            self.revert_type = 'revert'
            err_msg = exc['data'][len(ERROR_SIG):]
            err_msg, = eth_abi.decode(['string'], HexBytes(err_msg))
            self.revert_msg = err_msg
            return
        try:
            txid, data = next((k, v) for k, v in exc['data'].items() if k.
                startswith('0x'))
            self.revert_type = data['error']
        except StopIteration:
            raise ValueError(exc['message']) from None
        self.txid = txid
        self.source = ''
        self.pc = data.get('program_counter')
        if self.pc and self.revert_type == 'revert':
            self.pc -= 1
        self.revert_msg = data.get('reason')
        self.dev_revert_msg = brownie.project.build._get_dev_revert(self.pc)
        if self.revert_msg is None and self.revert_type in ('revert',
            'invalid opcode'):
            self.revert_msg = self.dev_revert_msg
        elif self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg

    def __str__(self) ->str:
        if not hasattr(self, 'revert_type'):
            return str(self.message)
        msg = self.revert_type
        if self.revert_msg:
            msg = f'{msg}: {self.revert_msg}'
        if self.source:
            msg = f'{msg}\n{self.source}'
        return str(msg)

    def _with_attr(self, **kwargs) ->'VirtualMachineError':
        for key, value in kwargs.items():
            setattr(self, key, value)
        if self.revert_msg == 'Failed assertion':
            self.revert_msg = self.dev_revert_msg or self.revert_msg
        return self


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):

    def __init__(self, e: Type[psutil.Popen], compiler: str='Compiler') ->None:
        self.compiler = compiler
        err_json = yaml.safe_load(e.stdout_data)
        err = [(i.get('formattedMessage') or i['message']) for i in
            err_json['errors']]
        super().__init__(f'{compiler} returned the following errors:\n\n' +
            '\n'.join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass

#!/usr/bin/python3

import sys
from typing import Optional, Type

import eth_abi
import psutil
import yaml
from hexbytes import HexBytes

import brownie

# network

ERROR_SIG = "0x08c379a0"


class UnknownAccount(Exception):
    pass


class UndeployedLibrary(Exception):
    pass


class UnsetENSName(Exception):
    pass


class IncompatibleEVMVersion(Exception):
    pass


class RPCProcessError(Exception):
    def __init__(self, cmd: str, uri: str) -> None:
        super().__init__(f"Unable to launch local RPC client.\nCommand: {cmd}\nURI: {uri}")


class RPCConnectionError(Exception):
    def __init__(self, cmd: str, proc: psutil.Popen, uri: str) -> None:
        msg = (
            "Able to launch RPC client, but unable to connect."
            f"\n\nCommand: {cmd}\nURI: {uri}\nExit Code: {proc.poll()}"
        )
        if sys.platform != "win32":
            out = proc.stdout.read().decode().strip() or "  (Empty)"
            err = proc.stderr.read().decode().strip() or "  (Empty)"
            msg = f"{msg}\n\nStdout:\n{out}\n\nStderr:\n{err}"
        super().__init__(msg)


class RPCRequestError(Exception):
    pass


class MainnetUndefined(Exception):
    pass


class VirtualMachineError(Exception):

    """
    Raised when a call to a contract causes an EVM exception.

    Attributes
    ----------
    message : str
        The full error message received from the RPC client.
    revert_msg : str
        The returned error string, if any.
    revert_type : str
        The error type.
    pc : int
        The program counter where the error was raised.
    txid : str
        The transaction ID that raised the error.
    """

    def __init__(self, exc: ValueError) -> None:
        self.txid: str = ""
        self.source: str = ""
        self.revert_type: str = ""
        self.pc: Optional[int] = None
        self.revert_msg: Optional[str] = None
        self.dev_revert_msg: Optional[str] = None

        try:
            exc = exc.args[0]
        except Exception:
            pass

        if not (isinstance(exc, dict) and "message" in exc):
            raise ValueError(str(exc)) from None

        if "data" not in exc:
            raise ValueError(exc["message"]) from None

        self.message: str = exc["message"].rstrip(".")

        if isinstance(exc["data"], str):
            # handle parity exceptions - this logic probably is not perfect
            if not exc["data"].startswith(ERROR_SIG):
                err_msg = exc["data"]
                if err_msg.endswith("0x"):
                    err_msg = exc["data"][:-2].strip()
                raise ValueError(f"{self.message}: {err_msg}") from None

            self.revert_type = "revert"
            err_msg = exc["data"][len(ERROR_SIG) :]
            (err_msg,) = eth_abi.decode(["string"], HexBytes(err_msg))
            self.revert_msg = err_msg

            return

        try:
            txid, data = next((k, v) for k, v in exc["data"].items() if k.startswith("0x"))
            self.revert_type = data["error"]
        except StopIteration:
            raise ValueError(exc["message"]) from None

        self.txid = txid
        self.source = ""
        self.pc = data.get("program_counter")
        if self.pc and self.revert_type == "revert":
            self.pc -= 1

        self.revert_msg = data.get("reason")
        self.dev_revert_msg = brownie.project.build._get_dev_revert(self.pc)
        if self.revert_msg is None and self.revert_type in ("revert", "invalid opcode"):
            self.revert_msg = self.dev_revert_msg
        elif self.revert_msg == "Failed assertion":
            self.revert_msg = self.dev_revert_msg or self.revert_msg

    def __str__(self) -> str:
        if not hasattr(self, "revert_type"):
            return str(self.message)
        msg = self.revert_type
        if self.revert_msg:
            msg = f"{msg}: {self.revert_msg}"
        if self.source:
            msg = f"{msg}\n{self.source}"
        return str(msg)

    def _with_attr(self, **kwargs) -> "VirtualMachineError":
        for key, value in kwargs.items():
            setattr(self, key, value)
        if self.revert_msg == "Failed assertion":
            self.revert_msg = self.dev_revert_msg or self.revert_msg  # type: ignore
        return self


class TransactionError(Exception):
    pass


class EventLookupError(LookupError):
    pass


class NamespaceCollision(AttributeError):
    pass


# project/


class ContractExists(Exception):
    pass


class ContractNotFound(Exception):
    pass


class ProjectAlreadyLoaded(Exception):
    pass


class ProjectNotFound(Exception):
    pass


class BadProjectName(Exception):
    pass


class CompilerError(Exception):
    def __init__(self, e: Type[psutil.Popen], compiler: str = "Compiler") -> None:
        self.compiler = compiler

        err_json = yaml.safe_load(e.stdout_data)
        err = [i.get("formattedMessage") or i["message"] for i in err_json["errors"]]
        super().__init__(f"{compiler} returned the following errors:\n\n" + "\n".join(err))


class IncompatibleSolcVersion(Exception):
    pass


class IncompatibleVyperVersion(Exception):
    pass


class PragmaError(Exception):
    pass


class InvalidManifest(Exception):
    pass


class UnsupportedLanguage(Exception):
    pass


class InvalidPackage(Exception):
    pass


class BrownieEnvironmentError(Exception):
    pass


class BrownieCompilerWarning(Warning):
    pass


class BrownieEnvironmentWarning(Warning):
    pass


class InvalidArgumentWarning(BrownieEnvironmentWarning):
    pass


class BrownieTestWarning(Warning):
    pass


class BrownieConfigWarning(Warning):
    pass
