MALICIOUS CONTRACT CAN BE DEPLOYED AT THE `proxyAddress` BY AN ATTACKER USING `CREATE2` THUS DELEGATING THE VOTES TO THE MALICIOUS CONTRACT FROM THE `source` PROXY ADDRESS
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/main/contracts/ERC20MultiDelegate.sol#L202-L214
https://github.com/code-423n4/2023-10-ens/blob/main/contracts/ERC20MultiDelegate.sol#L179-L189


# Vulnerability details

## Impact

The `ERC20MultiDelegate.delegateMulti` function is used to execute the delegation transfer process for multiple source and target delegates. The `delegateMulti` function calls the `_delegateMulti` function which in turn calls the `_processDelegation` if the `transferIndex < Math.min(sourcesLength, targetsLength)` condition is satisfied.

The `_processDelegation` function calls the `deployProxyDelegatorIfNeeded(target)` function which deploys a new `ERC20ProxyDelegator` contract if a `proxyAddress` does not already exist for `token, delegate` pair.

Now let's consider the following scenario:

1. The `_processDelegation` function is called for a specific combination of `source, target, amount`. 
2. The `deployProxyDelegatorIfNeeded` function is called as shown below:

    deployProxyDelegatorIfNeeded(target);

3. In the `deployProxyDelegatorIfNeeded` function the `retrieveProxyContractAddress(token, delegate)` function call will calculate the `proxyAddress` and let's assume there is no contract residing at this proxy address as of now.

4. Now the problem is an attacker can front-run the `delegateMulti` transaction and can deploy his own malicious contract at the `proxyAddress` contract for the given `target` delegate address. This is possible because attacker has all the required details to deploy the malicious contract at the `proxyAddress` deterministic address using the `CREATE2` opcode.

Attacker knows the `bytecode` of the `ERC20ProxyDelegator` contract.
Attacker knows the `0xff` is used.
Attacker knows the deployed address of the `ERC20MultiDelegate` (`address(this)`) contract.
Attacker knows the `salt` which is hardcoded to `uint256(0)`

Hence attacker can pre compute the deterministic `proxyAddress` address and deploy a malicious contract in computed `ProxyAddress` address.

5. The `proxyAddress` is calculated inside the `retrieveProxyContractAddress` function is calculated as shown below:

        bytes memory bytecode = abi.encodePacked(
            type(ERC20ProxyDelegator).creationCode,
            abi.encode(_token, _delegate) 
        );
        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff),
                address(this),
                uint256(0), // salt
                keccak256(bytecode)
            )
        );

6. Since the attacker `front-ran` the `delegateMulti` tranaction and deployed a malicious contract at the `porxyAddress`, inside the `deployProxyDelegatorIfNeeded` function the following condition will not be executed since the `bytecodeSize != 0`.  

        if (bytecodeSize == 0) {
            new ERC20ProxyDelegator{salt: 0}(token, delegate); 
            emit ProxyDeployed(delegate, proxyAddress);
        }

As a result the `proxyAddress