Flow

Sablier
FoundryDeFi
20,000 USDC
View results
Submission Details
Severity: low
Valid

ERC-721 metadata extension: incorrect implementation

Summary

SablierFlow.sol uses the ERC-721 metadata extension. According to the official documentation,

The supportsInterface method MUST return true when called with 0x49064906.

Source: https://eips.ethereum.org/EIPS/eip-4906

In contrast to that, the actual implementation returns false when the function is called with 0x49064906.

Vulnerability Details

While looking through the source code, we can see that the events MetadataUpdate and BatchMetadataUpdate are implemented correctly. We can also see that there are references to the ERC-4906 standard:

grep -r "4906" src/
src/abstracts/SablierFlowBase.sol: /// @dev Emits an ERC-4906 event to trigger an update of the NFT metadata.
src/interfaces/ISablierFlowBase.sol:import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol";
src/interfaces/ISablierFlowBase.sol: IERC4906, // 2 inherited components

However, the supportsInterface function call does not return true for the parameter "0x49064906".

Impact

External integrations that rely on the correct return value of this function may fail. Third party integrations may become problematic, hindering the widespread adoption of the project.

Tools Used and Proof of Concept

The following foundry test serves as a simple PoC:

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.22;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ud21x18, UD21x18 } from "@prb/math/src/UD21x18.sol";
import { Errors } from "src/libraries/Errors.sol";
import { Broker, Flow } from "src/types/DataTypes.sol";
import { Base_Test } from "../Base.t.sol";
contract Audit_Test is Base_Test {
function setUp() public virtual override {
Base_Test.setUp();
}
function test1() public view {
bytes4 interfaceId = 0x49064906;
bool result = flow.supportsInterface(interfaceId);
// Assert that the result is true
assertTrue(result, "The contract does not support the interface ID 0x49064906");
}
}

Execution of the test case yields:

[9076] Audit_Test::test1()
├─ [559] Flow::supportsInterface(0x49064906) [staticcall]
│ └─ ← [Return] false
├─ [0] VM::assertTrue(false, "The contract does not support the interface ID 0x49064906") [staticcall]
│ └─ ← [Revert] The contract does not support the interface ID 0x49064906
└─ ← [Revert] The contract does not support the interface ID 0x49064906

Recommendations

Implement the function as described in the ERC-4906 specification.

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

EIP4906

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.