Flow

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

SablierFlow is not fully EIP 4906 compliant

Summary

SablierFlow implements the IERC4906 interface and various tenets of the EIP-4906 standard but not the supportsInterface, which causes that the flow streams cannot be identified as EIP-4906 compliant by external integrations.

Vulnerability Details

First, we see that the flow contract is ISablierFlow and implements EIP-4906 MetadataUpdate extension for ERC721 tokens.

contract SablierFlow is
Batch, // 0 inherited components
NoDelegateCall, // 0 inherited components
ISablierFlow, // 4 inherited components
SablierFlowBase // 8 inherited components
{

From EIP-4906's motivation,

Many EIP-721 contracts emit an event when one of its tokens’ metadata are changed. While tracking changes based on these different events is possible, it is an extra effort for third-party platforms, such as an NFT marketplace, to build individualized solutions for each NFT collection.

Having a standard MetadataUpdate event will make it easy for third-party platforms to timely update the metadata of many NFTs

The codebase for the most part strictly adheres to the standard by constantly emitting the ERC-4906 event to trigger an update of the NFT metadata through the updateMetadata modifier. We can see that virtually of the the function that affects the flow emits this event, indicating a strict compliance to the standard.

However, the contract is still missing the supportsInterface function, making it not fully compliant.

According to the standard, the supports interface MUST return true when called with 0x49064906.

The MetadataUpdate or BatchMetadataUpdate event MUST be emitted when the JSON metadata of a token, or a consecutive range of tokens, is changed.

...

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

But from the test below which can be addded to any of the integration test files, we can see that it doesn't. It only returns true for ERC721 and ERC165 interface Ids.

function test_interface() public {
assertTrue(flow.supportsInterface(bytes4(0x80ac58cd))); /// ERC721
assertTrue(flow.supportsInterface(bytes4(0x01ffc9a7))); /// ERC165
assertFalse(flow.supportsInterface(bytes4(0x49064906))); /// ERC4906
}

Impact

Lack of full compliance with the standard. Also, since the flow will be used in tandem with other external contracts and integrations for actions like rewards distributions, external integrations that rely on qeurying its supportsInterface to verify its ERC4906 compliance will not be able properly do so due to its non-existence in the contract.

Tools Used

Manual review

Recommendations

Introduce the supportsInterface function.

function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId);
}
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.