xanoutas/solidity-security-findings huggingface dataset:
This code is not wroking `amounts[:sourcesLength]`
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L111


# Vulnerability details

## Impact
it is not going to work the whole protocol

## Proof of Concept
I tried that in Remix and it isn't compiling 

## Tools Used
manual
## Recommended Mitigation Steps

remove the code and write to manual slice the amounts array


## Assessed type

Other
Delegation Transfer Bug in ERC20MultiDelegate Contract
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/main/contracts/ERC20MultiDelegate.sol#L57


# Vulnerability details


## Description
 The _delegateMulti function has an issue with the logic for handling remaining source and target amounts after the transfer process. The incorrect handling of these amounts can lead to inconsistent state and potential loss of tokens during delegation transfers.

## Explanation

The bug in the ERC20MultiDelegate contract lies within the _delegateMulti function. This function iterates through the arrays of sources, targets, and amounts, and performs the delegation transfer. However, the bug arises from the incorrect handling of the remaining source and target amounts after each transfer.

Currently, the function adds the amount to _delegations[source][target] correctly, but it fails to deduct the amount from the remaining balance of the source. As a result, the delegations are updated correctly, but the source's balance is not reduced accordingly, leading to an inconsistent state in token ownership.

## Impact
This bug can result in tokens being improperly transferred or lost during delegation transfers. It can affect the accuracy of balances for source and target delegates, leading to incorrect voting power and potential financial losses.



## Proof of Concept 


     import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";

     contract ERC20VotesMock is ERC1155Burnable {
       constructor() ERC1155("Mock Token") {
         _mint(msg.sender, 1, 100, "");
       }

       function delegate(address) external {
        // delegate implementation
       }
     }

     contract ERC20VotesProxyMock {
       ERC20VotesMock public token;

       constructor() {
         token = new ERC20VotesMock();
       }

       function testDelegateMulti() external {
         ERC20MultiDelegate multiDelegate = new ERC20MultiDelegate(token, "");
         uint256[] memory sources = new uint256[](1);
         uint256[] memory targets = new uint256[](1);
         uint256[] memory amounts = new uint256[](1);
         sources[0] = uint256(msg.sender);
         targets[0] = uint256(address(this));
         amounts[0] = 50;
         multiDelegate.delegateMulti(sources, targets, amounts);
       }
     }


## Recommendation

To fix this bug, the _delegateMulti function should be refactored to correctly handle the remaining source and target amounts. The logic for processing delegation transfers, reimbursing remaining source amounts, and creating proxy delegators should be reevaluated and updated to ensure consistent and accurate token transfers.




## Assessed type

Other
blockStuffing attack can prevent from calling delegateMulti
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L116


# Vulnerability details

## Impact
blockStuffing attack prevent from getting votes

## Proof of Concept
that's how block stuffing work .https://medium.com/hackernoon/the-anatomy-of-a-block-stuffing-attack-a488698732ae
If user can't get vote in times , there might be exploitable for attaker While that is profitable .

## Tools Used
manual view
## Recommended Mitigation Steps




## Assessed type

DoS
Malicious Delegator can front-run transaction
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/main/contracts/ERC20MultiDelegate.sol#L65-L116
https://github.com/code-423n4/2023-10-ens/blob/main/contracts/ERC20MultiDelegate.sol#L144-L149


# Vulnerability details

## Impact
A Malicious delegator can divert delegate tokens by front-running transactions while processing multi-delegation

## Proof of Concept
During multi delegation process initiated by the "_delegateMulti" function, remaining source amounts are returned to msg.sender via the reImburse function. Which is subsequently sent to the target address from the msg.sender through the "createProxyDelegatorAndTransfer" function.
A malicious delegator in charge of delegation can however divert source amounts meant to be re-imbursed to msg.sender before they are processed to the target addresses through the "createProxyDelegatorAndTransfer" function. 
```solidity
    function delegateMulti(
        uint256[] calldata sources,
        uint256[] calldata targets,
        uint256[] calldata amounts
    ) external {
        _delegateMulti(sources, targets, amounts);
    }

    function _delegateMulti(
        uint256[] calldata sources,
        uint256[] calldata targets,
        uint256[] calldata amounts
    ) internal {
        uint256 sourcesLength = sources.length;
        uint256 targetsLength = targets.length;
        uint256 amountsLength = amounts.length;

        require(
            sourcesLength > 0 || targetsLength > 0,
            "Delegate: You should provide at least one source or one target delegate"
        );

        require(
            Math.max(sourcesLength, targetsLength) == amountsLength,
            "Delegate: The number of amounts must be equal to the greater of the number of sources or targets"
        );

        // Iterate until all source and target delegates have been processed.
        for (
            uint transferIndex = 0;
            transferIndex < Math.max(sourcesLength, targetsLength);
            transferIndex++
        ) {
            address source = transferIndex < sourcesLength
                ? address(uint160(sources[transferIndex]))
                : address(0);
            address target = transferIndex < targetsLength
                ? address(uint160(targets[transferIndex]))
                : address(0);
            uint256 amount = amounts[transferIndex];

            if (transferIndex < Math.min(sourcesLength, targetsLength)) {
                // Process the delegation transfer between the current source and target delegate pair.
                _processDelegation(source, target, amount);
            } else if (transferIndex < sourcesLength) {
                // Handle any remaining source amounts after the transfer process.
                _reimburse(source, amount);
            } else if (transferIndex < targetsLength) {
                // Handle any remaining target amounts after the transfer process.
                createProxyDelegatorAndTransfer(target, amount);
ERC20MultiDelegate's `_processDelegation` transfers tokens without checking delegate proxy contract approvals, risking transfer failures.
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L134
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L163-L171


# Vulnerability details

## Impact

In the `_processDelegation()` function, it transfers tokens between the source and target delegate proxy contracts using `transferFrom()`.

## Details

In the `_processDelegation()` function, it transfers tokens between the source and target delegate proxy contracts using `transferFrom()`. 

However, it does not check that the proxy contracts have approved the ERC20MultiDelegate contract to spend their tokens.

For example:

1. User A deposits 100 tokens to delegate address X
2. ERC1155 balance for delegate X is 100
3. ERC20MultiDelegate tries to transfer 50 tokens from X to Y
4. But the proxy for X has not approved ERC20MultiDelegate
5. So the `transferFrom()` will fail

This could happen if:

- The user deposits to a delegate address without going through ERC20MultiDelegate
- The proxy contract does not automatically approve ERC20MultiDelegate

## Proof of Concept

**[_processDelegation()](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L134)**

```solidity
function _processDelegation(
    address source, 
    address target,
    uint256 amount
) internal {

  // ...

  transferBetweenDelegators(source, target, amount);

  // ...

}
```

**[transferBetweenDelegators](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L163-L171)**

```solidity
function transferBetweenDelegators(
    address from,
    address to,
    uint256 amount  
) internal {

  address proxyAddressFrom = retrieveProxyContractAddress(token, from);
  address proxyAddressTo = retrieveProxyContractAddress(token, to);
  
  token.transferFrom(proxyAddressFrom, proxyAddressTo, amount);

}
```

The `transferFrom()` call assumes that `proxyAddressFrom` has approved the ERC20MultiDelegate contract to spend amount tokens on its behalf. 

However, there is no check or enforcement that `proxyAddressFrom` has actually approved the contract.

This could lead to the `transferFrom()` reverting if the proxy contract has not provided approval after being deployed.

The approval needs to be handled either:

- In `deployProxyDelegatorIfNeeded()` after deploying the proxy
- Or on first transfer by approving if `transferFrom()` reverts

The key lines are the `transferFrom()` in `transferBetweenDelegators()` which relies on an approval that is not enforced.

## Contextual Explanation

The ERC20MultiDelegate contract acts as a middleman to transfer voting power (tokens) between different delegate addresses. 

It uses the ERC1155 token to track balances for each delegate. When a user wants to move voting power between delegates, the ERC20MultiD
Reimbursing leftover funds in _reimburse() lacks authentication, enabling potential theft.
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L144-L149
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L148


# Vulnerability details

## Impact

Leftover source amounts are sent back to the caller's address using `_reimburse()`. Extra target amounts are deposited from the caller.

## Proof of Concept

When there are leftover source amounts after transferring between delegates, the contract calls `_reimburse()` to send the leftover amount back to the original caller's address.

However, this leaves a window where someone else could call `_reimburse()` before the original caller and steal their funds.

The issue is:

- `_processDelegation()` withdraws from the source proxy into the contract
- It only transfers the input amount to the target
- Leftover source amount stays in the contract
- `_reimburse()` is used to send it back to the caller

But `_reimburse()` can be called by anyone, not just the original caller.

So an attacker could:

1. See leftover funds in the contract after `_processDelegation()` 
2. Quickly call `_reimburse()` before the original caller
3. Steal the leftover source funds

The main vulnerability occurs **[in the _reimburse() function](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L144-L149)**:

```solidity
function _reimburse(address source, uint256 amount) internal {

  // THIS LINE IS THE ISSUE
  token.transferFrom(proxyAddressFrom, msg.sender, amount);

}
```

Specifically, this line of code: **[Line 148](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L148)**

```solidity
token.transferFrom(proxyAddressFrom, msg.sender, amount);
```

Is transferring leftover funds to `msg.sender` without any checks.

This allows anyone to call `_reimburse()` and steal funds by passing their own address as `msg.sender`. 

Some additional context:
- _reimburse() is called from `_processDelegation()` after transferring between delegates
- `proxyAddressFrom` is the source delegate proxy that contains leftover funds
- amount is the leftover amount after partial delegation transfer

So in summary, the root cause is transferring funds to unauthenticated `msg.sender` in `_reimburse()`.

**Contextual Explanation**

The key functions involved are:

`_processDelegation()`:

- Withdraws `amount` tokens from `sourceProxy` contract into itself
- Transfers `amount` tokens to `targetProxy` 
- Leftover tokens remain in contract balance

`_reimburse()`:

- Sends leftover amount to `msg.sender`
- No authentication on who can call it

**Exploit Flow**

1. Attacker calls `delegateMulti()` with:
   - `sourceProxy` containing 100 tokens 
   - `targetProxy` 
   - `amount` = 75

2. `_processDelegation() is called:
   - Withdraws 100 tokens from `sourceP
Failure to validate token balances enables unauthorized withdrawal and potential theft.
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L137
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L137
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L192-L196


# Vulnerability details

## Impact

There is no check that the amounts match the actual token balances of the source delegates. A caller could withdraw more tokens than they have delegated.

## Proof of Concept

In the **[_processDelegation()](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L137)** function:

```solidity
function _processDelegation(
        address source,
        address target,
        uint256 amount
    ) internal {

        uint256 balance = getBalanceForDelegate(source);

        // Issue is on this line:
        assert(amount <= balance);  

        deployProxyDelegatorIfNeeded(target);
        transferBetweenDelegators(source, target, amount);
  
        emit DelegationProcessed(source, target, amount);
    }
```

The assert statement only checks that the passed in amount is less than the NFT balance tracked for that source delegate. 

It does not check the actual token balance held by the source delegate's proxy contract.

This means the caller could withdraw more tokens than they actually have delegated.


The lack of proper token balance validation in the `_processDelegation()` function is a major security issue that could allow attackers to steal funds.

The core problem is that [`_processDelegation()`](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L124-L137) relies solely on the NFT balances tracked internally by the contract to validate the amount being transferred. 

It calls **[getBalanceForDelegate()](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L192-L196)** which only returns the `balanceOf` the NFT for that source delegate.

This does NOT reflect the actual underlying token balance held by that delegate's proxy contract.

So a malicious caller could:

1. Deposit 100 tokens and delegate them to a source via the `delegateMulti()` function. This would mint an NFT with a balance of 100. 

2. Then call `delegateMulti()` again to transfer funds from that source to a target. But specify an amount greater than 100 tokens. 

3. The `_processDelegation()` function would see the NFT balance is 100, and the assert statement would pass. Even though the actual proxy contract holds less than the requested amount.

4. When `transferBetweenDelegators()` is called, it would succeed in transferring MORE tokens than were originally delegated. Essentially stealing funds.

This is possible because the pro
Lack of delegation revocation leads to accumulating zombie delegations over time.
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63


# Vulnerability details

## Impact

There is no way to revoke delegations other than transferring to a zero address target. This means zombie delegations could build up.

## Proof of Concept

The contract lacks a proper way to revoke delegations. 

The issue occurs in the **[delegateMulti() function](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63)**, which is the only way to update delegations:

```solidity
function delegateMulti(
  uint256[] calldata sources,
  uint256[] calldata targets,
  uint256[] calldata amounts
) external {

  // Issue is here:
  _delegateMulti(sources, targets, amounts);

}
```

The function only allows delegating to new target addresses by minting new NFTs. 

There is no way for a user to "undelegate" or revoke existing delegations, other than transferring to the zero address.

This means that old delegations could build up over time as zombie NFTs that users can't remove.


The lack of delegation revocation in `delegateMulti()` is a major limitation that can lead to zombie delegations accumulating over time. 

Let me provide an in-depth explanation:

The problem is that `delegateMulti()` only allows for delegating tokens to new target addresses by minting new NFTs. There is no functionality for the user to "undelegate" or burn these NFTs to revoke existing delegations.

This means once a user delegates to a target, the only way to undo that delegation is by re-delegating the entire balance to the zero address. This is very inefficient.

Over time, as users switch between different delegates, these zombie delegations where tokens were revoked by sending to zero could build up.

These zombie NFTs remain under the user's account, even though they no longer correspond to actual delegations. 

The end result is the internal NFT balances become disconnected from reality. Users are unable to revoke delegations in a clean manner.

Considering this clear proof of the revocation issue is important to demonstrate the problem. Here is an example:

```solidity

// User delegates 100 tokens to Delegate A 
delegate.delegateMulti([0], [DelegateA], [100])

// User NFT balance = 1
// NFT ID 1 represents DelegateA

// User wants to revoke delegation to DelegateA

// User can redelegate to zero address 
delegate.delegateMulti([DelegateA], [0], [100]) 

// But their NFT balance is still 1! 
// NFT ID 1 is now a zombie delegation

// There should be a way for user to burn NFT directly:

function revokeDelegation(uint256 delegateId) {
  burn(delegateId);
}

// This would let the user clean up their delegations
// And fix the NFT accounting

```
- Users are unable to revoke delegations directly

- Redelegating to zero leaves zombie NFTs

- No way to burn NFTs to match intended delegations

## Tools Used

Vs

## Recomm
The `delegateMulti` function lacks checks on total delegation amounts, enabling over-delegation.
Audit: 2023-10-ens-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63


# Vulnerability details

## Impact

The `delegateMulti` function lacks a way to limit total delegation amounts, so one could over-delegate.

## Proof of Concept

Seeing the `delegateMulti` function does not check or limit the total amount being delegated. This could allow users to over-delegate their token balance.

The issue occurs in the [`delegateMulti`](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63) function definition:

```solidity
function delegateMulti(
  uint256[] calldata sources,
  uint256[] calldata targets,
  uint256[] calldata amounts
) external {

  // Issue is here - no check on total amount

  _delegateMulti(sources, targets, amounts); 

}
```

There is no check on the total sum of all values in the amounts array.

This means a user could call [delegateMulti](https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L57-L63) and pass in amounts that add up to more tokens than they actually hold.

For example:

```solidity
User balance: 100 tokens

delegateMulti([Delegate1], [Delegate2], [80]); 

delegateMulti([Delegate3], [Delegate4], [50]);

Total delegated: 80 + 50 = 130 > 100 (user's balance)
```

This would let the user over-delegate their tokens across multiple delegates.

The lack of total amount validation in `delegateMulti` is a critical issue that can lead to over-delegation.

The main problem is `delegateMulti` relies solely on validating amounts at the individual delegation level in `_processDelegation`. There is no check on the total summed amounts.

A clear proof of over-delegation here is an example to demonstrate:

```solidity

// User has 100 tokens
uint userBalance = 100;

// User delegates 80 tokens to DelegateA
delegate.delegateMulti([0], [DelegateA], [80]) 

// Passes individual validation in _processDelegation

// User then delegates 50 tokens to DelegateB
delegate.delegateMulti([0], [DelegateB], [50])

// Passes individual validation again

// Total delegated is 80 + 50 = 130 tokens
// Exceeds user's actual balance of 100 tokens

// User has over-delegated!

```
- Each individual delegation passes amount validation 

- But total delegated across multiple calls exceeds balance

- Lack of total amount check allows over-delegation

## Tools Used

Vs

## Recommended Mitigation Steps

Could be prevented by adding a check on the total amounts sum in `delegateMulti`:

```solidity

uint256 total = amounts.reduce(add);

require(total <= token.balanceOf(msg.sender), "Insufficient balance");

_delegateMulti(sources, targets, amounts);

```


## Assessed type

Invalid Validation