From e6ee3ee2338687627e6548a9c5d7fae9362e2543 Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Sat, 10 Feb 2024 13:58:29 +0200 Subject: [PATCH] refactor: change information when the nft is non-transferable --- src/SablierV2NFTDescriptor.sol | 10 ++++- test/mocks/NFTDescriptorMock.sol | 3 +- .../nft-descriptor/generateDescription.t.sol | 42 +++++++++++++++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/SablierV2NFTDescriptor.sol b/src/SablierV2NFTDescriptor.sol index 5601cc2e1..65c36ce5c 100644 --- a/src/SablierV2NFTDescriptor.sol +++ b/src/SablierV2NFTDescriptor.sol @@ -88,6 +88,7 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { }), ',"description":"', generateDescription({ + isTransferable: vars.sablier.isTransferable(streamId), streamingModel: vars.streamingModel, assetSymbol: vars.assetSymbol, streamId: streamId.toString(), @@ -248,6 +249,7 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { /// @notice Generates a string with the NFT's JSON metadata description, which provides a high-level overview. function generateDescription( + bool isTransferable, string memory streamingModel, string memory assetSymbol, string memory streamId, @@ -258,6 +260,12 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { pure returns (string memory) { + // Depending on the transferability of the NFT, declare the relevant information. + string memory info = isTransferable + ? + unicode"⚠️ WARNING: Transferring the NFT makes the new owner the recipient of the stream. The funds are not automatically withdrawn for the previous recipient." + : unicode"❕INFO: This NFT is non-transferable. It cannot be sold or transferred to another account."; + return string.concat( "This NFT represents a payment stream in a Sablier V2 ", streamingModel, @@ -274,7 +282,7 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { " Address: ", assetAddress, "\\n\\n", - unicode"⚠️ WARNING: Transferring the NFT makes the new owner the recipient of the stream. The funds are not automatically withdrawn for the previous recipient." + info ); } diff --git a/test/mocks/NFTDescriptorMock.sol b/test/mocks/NFTDescriptorMock.sol index 6d93fb7d8..62f59eff3 100644 --- a/test/mocks/NFTDescriptorMock.sol +++ b/test/mocks/NFTDescriptorMock.sol @@ -52,6 +52,7 @@ contract NFTDescriptorMock is SablierV2NFTDescriptor { } function generateDescription_( + bool isTransferable, string memory streamingModel, string memory assetSymbol, string memory streamId, @@ -62,7 +63,7 @@ contract NFTDescriptorMock is SablierV2NFTDescriptor { pure returns (string memory) { - return generateDescription(streamingModel, assetSymbol, streamId, sablierAddress, assetAddress); + return generateDescription(isTransferable, streamingModel, assetSymbol, streamId, sablierAddress, assetAddress); } function generateName_( diff --git a/test/unit/concrete/nft-descriptor/generateDescription.t.sol b/test/unit/concrete/nft-descriptor/generateDescription.t.sol index 8a295e59e..f53bef905 100644 --- a/test/unit/concrete/nft-descriptor/generateDescription.t.sol +++ b/test/unit/concrete/nft-descriptor/generateDescription.t.sol @@ -5,11 +5,13 @@ pragma solidity >=0.8.22 <0.9.0; import { NFTDescriptor_Unit_Concrete_Test } from "./NFTDescriptor.t.sol"; contract GenerateDescription_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_Test { - string internal constant DISCLAIMER = + string internal constant INFO_NON_TRANSFERABLE = + unicode"❕INFO: This NFT is non-transferable. It cannot be sold or transferred to another account."; + string internal constant INFO_TRANSFERABLE = unicode"⚠️ WARNING: Transferring the NFT makes the new owner the recipient of the stream. The funds are not automatically withdrawn for the previous recipient."; function test_GenerateDescription_Empty() external { - string memory actualDescription = nftDescriptorMock.generateDescription_("", "", "", "", ""); + string memory actualDescription = nftDescriptorMock.generateDescription_(true, "", "", "", "", ""); string memory expectedDescription = string.concat( "This NFT represents a payment stream in a Sablier V2 ", " contract. The owner of this NFT can withdraw the streamed assets, which are denominated in ", @@ -20,13 +22,45 @@ contract GenerateDescription_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_T "\\n- ", " Address: ", "\\n\\n", - DISCLAIMER + INFO_TRANSFERABLE + ); + assertEq(actualDescription, expectedDescription, "metadata description"); + } + + function test_GenerateDescription_NonTransferable() external { + string memory actualDescription = nftDescriptorMock.generateDescription_( + false, + "Lockup Linear", + dai.symbol(), + "42", + "0x78B190C1E493752f85E02b00a0C98851A5638A30", + "0xFEbD67A34821d1607a57DD31aae5f246D7dE2ca2" + ); + string memory expectedDescription = string.concat( + "This NFT represents a payment stream in a Sablier V2 ", + "Lockup Linear", + " contract. The owner of this NFT can withdraw the streamed assets, which are denominated in ", + dai.symbol(), + ".\\n\\n", + "- Stream ID: ", + "42", + "\\n- ", + "Lockup Linear", + " Address: ", + "0x78B190C1E493752f85E02b00a0C98851A5638A30", + "\\n- ", + "DAI", + " Address: ", + "0xFEbD67A34821d1607a57DD31aae5f246D7dE2ca2", + "\\n\\n", + INFO_NON_TRANSFERABLE ); assertEq(actualDescription, expectedDescription, "metadata description"); } function test_GenerateDescription() external { string memory actualDescription = nftDescriptorMock.generateDescription_( + true, "Lockup Linear", dai.symbol(), "42", @@ -50,7 +84,7 @@ contract GenerateDescription_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_T " Address: ", "0xFEbD67A34821d1607a57DD31aae5f246D7dE2ca2", "\\n\\n", - DISCLAIMER + INFO_TRANSFERABLE ); assertEq(actualDescription, expectedDescription, "metadata description"); }