Platform: Code4rena
Start Date: 05/10/2023
Pot Size: $33,050 USDC
Total HM: 1
Participants: 54
Period: 6 days
Judge: hansfriese
Id: 294
League: ETH
Rank: 5/54
Findings: 1
Award: $1,774.19
🌟 Selected for report: 0
🚀 Solo Findings: 0
1774.1935 USDC - $1,774.19
https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L148 https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L160 https://github.com/code-423n4/2023-10-ens/blob/ed25379c06e42c8218eb1e80e141412496950685/contracts/ERC20MultiDelegate.sol#L170
The contract is using the ERC20 transferFrom
function to transfer tokens to/from the user to the proxy or in between different proxy contracts.
However, as the return value is not checked it might fail silently for some Tokens
This can finally lead to an vulnerability where an attacker can steal all the delegated Tokens.
Classifying this as a Medium, as these Tokens are quite rare, but still the sponsor mentioned that the contract should work with any Token that complies to the ERC20Votes interface.
Every time the delegateMulti
function is called by a user, the contract is transferring amounts of the underlying ERC20 token. For this the ERC20 transferFrom
function is used.
According to the ERC20 specification, this function has to return an boolean to indicate it´s success. Most of the implementations also revert on a failed transfer, this is the case for the ENSToken, too.
However, not all implementations will revert all the time, therefore the return value of the transferFrom
call should be checked to make sure the transfer did not fail.
This is not done inside the ERC20MultiDelegate
contract, therefore the risk of a silently failing transfer exists. This is a problem because it can result in a loss of funds.
Example:
A malicious user has no Voting Tokens, but knows that the transferFrom
on this token does not revert on any failure, but returns false.
The user also knows that alice has delegated 10 Tokens to Bob already.
delegateMulti([],[bob],[10])
.delegateMulti([bob],[],[10])
to reimbures the ERC1155 Tokens for the voting Tokens.--> As a result the attacker was able to steal Alice´s Tokens
Example2:
Alice wants to delegate 10 Tokens to Bob and calls delegateMulti([],[bob],[10])
to achieve this.
The contract will do the following:
transferFrom(alice,proxyBob,10)
(We imagine this transfer to work as expected)Now Alice wants to undelegate 5 of these tokens from Bob and get them back. Therefore she calls delegateMulti([bob],[],[5])
Now the contract is doing the following:
transferFrom(proxyBob,alice,5)
(this time this transfer silently fails)Because of the silently failed transfer, Alice would end up with no Tokens returned and only 5 ERC1155 Tokens left (Lost 5 Tokens)
Manual review
The return value of the transferFrom
calls should be checked!
This could be done, but not has to, by using the SafERC20 Library from Openzeppelin.
Token-Transfer
#0 - c4-pre-sort
2023-10-12T07:09:38Z
141345 marked the issue as duplicate of #91
#1 - c4-pre-sort
2023-10-12T12:02:08Z
141345 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-24T17:11:28Z
hansfriese marked the issue as satisfactory
#3 - c4-judge
2023-10-28T06:23:32Z
hansfriese marked the issue as duplicate of #90
#4 - c4-judge
2023-10-28T06:29:47Z
hansfriese marked the issue as not a duplicate
#5 - c4-judge
2023-10-28T06:29:56Z
hansfriese changed the severity to 3 (High Risk)
#6 - c4-judge
2023-10-28T06:30:12Z
hansfriese marked the issue as duplicate of #91
#7 - c4-judge
2023-10-29T10:13:32Z
hansfriese changed the severity to 2 (Med Risk)