Repository: eth-brownie/brownie
Issue: Exception when deploying a self-destructing contract

### Environment information

* `brownie` Version: 1.8.5

### What was wrong?

I'm experimenting with create2 and made a contract that does some things and then calls `selfdestruct` at the end of the constructor. brownie didn't like this:

```
Running 'scripts.dev-deploy.main'...
Transaction sent: 0x36f1599c9b5b5ab9f243f5d0c64e8f2637a355818bc4cf5e1a67168e9e22713e
  Gas price: 0.0 gwei   Gas limit: 6721975
  ArgobytesOwnedVaultDeployer.constructor confirmed - Block: 1   Gas used: 3545980 (52.75%)
  ArgobytesOwnedVaultDeployer deployed at: 0x04246fAA61004668E1C0a388A3bF60E67827A17E

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/ski/code/argobytes-contracts-brownie/venv/lib/python3.8/site-packages/brownie/network/contract.py", line 190, in _add_from_tx
    self.at(tx.contract_address, tx.sender, tx)
  File "/home/ski/code/argobytes-contracts-brownie/venv/lib/python3.8/site-packages/brownie/network/contract.py", line 174, in at
    contract = ProjectContract(self._project, build, address, owner, tx)
  File "/home/ski/code/argobytes-contracts-brownie/venv/lib/python3.8/site-packages/brownie/network/contract.py", line 728, in __init__
    _DeployedContractBase.__init__(self, address, owner, tx)
  File "/home/ski/code/argobytes-contracts-brownie/venv/lib/python3.8/site-packages/brownie/network/contract.py", line 309, in __init__
    raise ContractNotFound(f"No contract deployed at {address}")
brownie.exceptions.ContractNotFound: No contract deployed at 0x04246fAA61004668E1C0a388A3bF60E67827A17E
```

### How can it be fixed?

I was expecting to get a transaction object back rather than a Contract. I'm not sure how that will interact with a contract failing to deploy for other reasons though.


Changed files:
brownie/network/contract.py

diff --git a/brownie/network/contract.py b/brownie/network/contract.py
index b2208f86..3671374c 100644
--- a/brownie/network/contract.py
+++ b/brownie/network/contract.py
@@ -352,6 +352,7 @@ class _DeployedContractBase(_ContractBase):
         tx: TransactionReceipt of the of the tx that deployed the contract."""
 
     _reverted = False
+    _initialized = False
 
     def __init__(
         self, address: str, owner: Optional[AccountsType] = None, tx: TransactionReceiptType = None
@@ -384,6 +385,8 @@ class _DeployedContractBase(_ContractBase):
                 self._check_and_set(abi["name"], overloaded)
             getattr(self, abi["name"])._add_fn(abi, natspec)
 
+        self._initialized = True
+
     def _check_and_set(self, name: str, obj: Any) -> None:
         if name == "balance":
             warnings.warn(
@@ -426,6 +429,14 @@ class _DeployedContractBase(_ContractBase):
         except AttributeError:
             raise AttributeError(f"Contract '{self._name}' object has no attribute '{name}'")
 
+    def __setattr__(self, name: str, value: Any) -> None:
+        if self._initialized and hasattr(self, name):
+            if isinstance(getattr(self, name), _ContractMethod):
+                raise AttributeError(
+                    f"{self._name}.{name} is a contract function, it cannot be assigned to"
+                )
+        super().__setattr__(name, value)
+
     def get_method_object(self, calldata: str) -> Optional["_ContractMethod"]:
         """
         Given a calldata hex string, returns a `ContractMethod` object.