Flow

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

Metadata is not updated as expected.

Summary

the report describes an issue in how metadata updated when using createAndDeposit function which is responsible for create and deposit
so _create is called then the _deposit but the issue is that NFT metadata is update only when stream is created not when deposit happens.
As a result, the updated balance from _deposit is not reflected in the metadata of the NFT,
which could lead to inconsistencies in how the stream’s current state is represented on-chain.

Vulnerability Details

In the createAndDeposit function, _create is called to set up a new stream and updateMetadata is subsequently called to capture the initial metadata state of the NFT.
However, updateMetadata is called before _deposit executes, which means the NFT metadata does not account for the balance update performed by _deposit.
Potential for Inaccurate Metadata.

POC:

function createAndDeposit(address sender, address recipient, UD21x18 ratePerSecond, IERC20 token, bool transferable, uint128 amount) external override noDelegateCall returns(uint256 streamId) {
// Checks, Effects, and Interactions: create the stream.
code streamId = _create(sender, recipient, ratePerSecond, token, transferable);
// Checks, Effects, and Interactions: deposit on stream.
_deposit(streamId, amount);
}
function _create(address sender, address recipient, UD21x18 ratePerSecond, IERC20 token, bool transferable) internal returns(uint256 streamId) {
//...
_streams[streamId] = Flow.Stream({
code balance: 0,
isStream: true,
isTransferable: transferable,
isVoided: false,
ratePerSecond: ratePerSecond,
sender: sender,
snapshotDebtScaled: 0,
snapshotTime: uint40(block.timestamp),
token: token,
tokenDecimals: tokenDecimals
});
//...
code _mint({ to: recipient, tokenId: streamId });
}
function _mint(address to, uint256 tokenId) internal {
//...
code address previousOwner = _update(to, tokenId, address(0));
}
code // as we see here updateMetadata modifier is called from _create function so when
// _create is executed and finished the updateMetadata modifier executes and
// emit MetadataUpdate({ _tokenId: streamId });
function _update(address to, uint256 streamId, address auth) internal override updateMetadata(streamId) returns(address) {
//...
}
modifier updateMetadata(uint256 streamId) {
_;
emit MetadataUpdate({ _tokenId: streamId });
}
function _deposit(uint256 streamId, uint128 amount) internal {
//...
code _streams[streamId].balance += amount;
//...
}

So now the NFT on market place will not be reflect with the actual balance.

Impact

The NFT metadata may display incorrect information, which can lead to user confusion or misunderstandings about the current balance of the stream.

Recommendations

Update metadata after _deposit happens.

Updates

Lead Judging Commences

inallhonesty Lead Judge
8 months ago
inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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