# Wallet Protocol Draft
## Implementation contract can be destroyed by anyone
**Severity**: High
**Context**: [`Implementation.sol#L17`](https://github.com/spearbit-audits/writing-exercise/blob/develop/contracts/Implementation.sol#L17)
- delegatecallContract can be called by anyone and call delegate call to any arbitrary address.
- If delegatecallContract is called directly rather than from proxy, and it delegates to a contract and that delegatee contract executes `SELFDESTRUCT` then the logic of proxy is erased and becomes `0x` leaving it unusable for all of the proxies.
**POC**
```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
contract Malicious {
function kill() external payable {
selfdestruct(payable(address(0)));
}
}
```
If `Implementation.delegatecallContract` is called directly (without using proxy) and delegates call to`Malicious`, then `Implementation` is destroyed
**Recommendations**
```diff
diff --git a/contracts/Implementation.sol b/contracts/Implementation.sol
index a7ab071..3bd3329 100644
--- a/contracts/Implementation.sol
+++ b/contracts/Implementation.sol
@@ -8,6 +8,12 @@ pragma solidity 0.8.10;
/// Only deployed once and the implementation is reused by all proxy contracts.
contract Implementation {
+ address immutable self;
+
+ constructor() {
+ self = address(this);
+ }
+
function callContract(address a, bytes calldata _calldata) payable external returns (bytes memory) {
(bool success , bytes memory ret) = a.call{value: msg.value}(_calldata);
require(success);
@@ -15,6 +21,7 @@ contract Implementation {
}
function delegatecallContract(address a, bytes calldata _calldata) payable external returns (bytes memory) {
+ require(address(this) != self);
(bool success, bytes memory ret) = a.delegatecall(_calldata);
require(success);
return ret;
```
- when the `Implementation` contract is deployed, register its real address in variable and on each delegatecall, compare execution context address with a real address, it should not be same to prevent it being called directly.