Clustered and overlapped text in SVG NFT metadata images that are generated from ReceiptRender.sol block users from correctly valuing the NFT #126
Labels
bug
Something isn't working
disagree with severity
Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments)
downgraded by judge
Judge downgraded the risk level of this issue
grade-b
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
Lines of code
https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/ReceiptRenderer.sol#L10
Vulnerability details
Impact
Clustered and overlapped text in SVG NFT metadata images that are generated from ReceiptRender.sol block users from correctly valuing the NFT
Proof of Concept
The POC attemps to generate a NFT metadata and extract the SVG image to render the image.
First, copy the whole code in the file below
https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/ReceiptRenderer.sol#L10
Then go to https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js
paste the code, complie the smart contract and deploy the smart contract to the local test network in remix
Then we can supply the parameter and call generateTokenURI view function in remix
tokenId: 10,
QuestId: 100,
totalParticipants: 20
claimed: false,
rewardAmount: 1000000000000
rewardAddress: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
The string generated in base64 format is:
data:application/json;base64,eyJuYW1lIjogIlJhYmJpdEhvbGUuZ2cgUmVjZWlwdCAjMTAiLCJkZXNjcmlwdGlvbiI6ICJSYWJiaXRIb2xlLmdnIFJlY2VpcHRzIGFyZSB1c2VkIHRvIGNsYWltIHJld2FyZHMgZnJvbSBjb21wbGV0ZWQgcXVlc3RzLiIsImltYWdlIjogImRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsUEhOMlp5QjRiV3h1Y3owaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1qQXdNQzl6ZG1jaUlIQnlaWE5sY25abFFYTndaV04wVW1GMGFXODlJbmhOYVc1WlRXbHVJRzFsWlhRaUlIWnBaWGRDYjNnOUlqQWdNQ0F6TlRBZ016VXdJajQ4YzNSNWJHVStMbUpoYzJVZ2V5Qm1hV3hzT2lCM2FHbDBaVHNnWm05dWRDMW1ZVzFwYkhrNklITmxjbWxtT3lCbWIyNTBMWE5wZW1VNklERTBjSGc3SUgwOEwzTjBlV3hsUGp4eVpXTjBJSGRwWkhSb1BTSXhNREFsSWlCb1pXbG5hSFE5SWpFd01DVWlJR1pwYkd3OUltSnNZV05ySWlBdlBqeDBaWGgwSUhnOUlqVXdKU0lnZVQwaU5EQWxJaUJqYkdGemN6MGlZbUZ6WlNJZ1pHOXRhVzVoYm5RdFltRnpaV3hwYm1VOUltMXBaR1JzWlNJZ2RHVjRkQzFoYm1Ob2IzSTlJbTFwWkdSc1pTSStVbUZpWW1sMFNHOXNaU0JSZFdWemRDQWpNVEF3UEM5MFpYaDBQangwWlhoMElIZzlJamN3SlNJZ2VUMGlOREFsSWlCamJHRnpjejBpWW1GelpTSWdaRzl0YVc1aGJuUXRZbUZ6Wld4cGJtVTlJbTFwWkdSc1pTSWdkR1Y0ZEMxaGJtTm9iM0k5SW0xcFpHUnNaU0krVW1GaVltbDBTRzlzWlNCUmRXVnpkQ0JTWldObGFYQjBJQ01BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUNqd3ZkR1Y0ZEQ0OEwzTjJaejQ9IiwiYXR0cmlidXRlcyI6IFt7InRyYWl0X3R5cGUiOiAiUXVlc3QgSUQiLCJ2YWx1ZSI6ICIxMDAifSx7InRyYWl0X3R5cGUiOiAiVG9rZW4gSUQiLCJ2YWx1ZSI6ICIxMCJ9LHsidHJhaXRfdHlwZSI6ICJUb3RhbCBQYXJ0aWNpcGFudHMiLCJ2YWx1ZSI6ICIyMCJ9LHsidHJhaXRfdHlwZSI6ICJDbGFpbWVkIiwidmFsdWUiOiAiZmFsc2UifSx7InRyYWl0X3R5cGUiOiAiUmV3YXJkIEFtb3VudCIsInZhbHVlIjogIjEwMDAwMDAwMDAwMDAifSx7InRyYWl0X3R5cGUiOiAiUmV3YXJkIEFkZHJlc3MiLCJ2YWx1ZSI6ICIweDI3OTFiY2ExZjJkZTQ2NjFlZDg4YTMwYzk5YTdhOTQ0OWFhODQxNzQifV19
Then we go to the website to decode the base64 string to a json object
https://onlinejsontools.com/convert-base64-to-json
The decodes json object is:
{"name": "RabbitHole.gg Receipt #10","description": "RabbitHole.gg Receipts are used to claim rewards from completed quests.","image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaW5ZTWluIG1lZXQiIHZpZXdCb3g9IjAgMCAzNTAgMzUwIj48c3R5bGU+LmJhc2UgeyBmaWxsOiB3aGl0ZTsgZm9udC1mYW1pbHk6IHNlcmlmOyBmb250LXNpemU6IDE0cHg7IH08L3N0eWxlPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9ImJsYWNrIiAvPjx0ZXh0IHg9IjUwJSIgeT0iNDAlIiBjbGFzcz0iYmFzZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UmFiYml0SG9sZSBRdWVzdCAjMTAwPC90ZXh0Pjx0ZXh0IHg9IjcwJSIgeT0iNDAlIiBjbGFzcz0iYmFzZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UmFiYml0SG9sZSBRdWVzdCBSZWNlaXB0ICMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjwvdGV4dD48L3N2Zz4=","attributes": [{"trait_type": "Quest ID","value": "100"},{"trait_type": "Token ID","value": "10"},{"trait_type": "Total Participants","value": "20"},{"trait_type": "Claimed","value": "false"},{"trait_type": "Reward Amount","value": "1000000000000"},{"trait_type": "Reward Address","value": "0x2791bca1f2de4661ed88a30c99a7a9449aa84174"}]}
We copy the image data and go to
https://onlinejsontools.com/convert-base64-to-json
again to decode the image from base64 text to svg format
the image data:
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaW5ZTWluIG1lZXQiIHZpZXdCb3g9IjAgMCAzNTAgMzUwIj48c3R5bGU+LmJhc2UgeyBmaWxsOiB3aGl0ZTsgZm9udC1mYW1pbHk6IHNlcmlmOyBmb250LXNpemU6IDE0cHg7IH08L3N0eWxlPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9ImJsYWNrIiAvPjx0ZXh0IHg9IjUwJSIgeT0iNDAlIiBjbGFzcz0iYmFzZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UmFiYml0SG9sZSBRdWVzdCAjMTAwPC90ZXh0Pjx0ZXh0IHg9IjcwJSIgeT0iNDAlIiBjbGFzcz0iYmFzZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UmFiYml0SG9sZSBRdWVzdCBSZWNlaXB0ICMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjwvdGV4dD48L3N2Zz4=
is decoded to:
<style>.base { fill: white; font-family: serif; font-size: 14px; }</style>RabbitHole Quest #100RabbitHole Quest Receipt #
We go to the website to view and render the generated SVG:
https://www.svgviewer.dev/
The image is linked below:
https://drive.google.com/file/d/10QSTcJL0HSubkGIMAYXjWmdA9Sb_XAT-/view
As we can see ,the text in the NFT metadata image are clustered and overlapped, from user's prespective, it is difficult to value the NFT correctly just by look at the image.
The impact is severe, the third party marketplace relies on the tokenURI and the image to correctly display the NFT image to end user, end user may be confused and has no desire to trade the NFT if he see such clustered text in the metadata image.
Tools Used
Manual Review
Recommended Mitigation Steps
We recommend the protocol adjust the layout (parameter of x and y and width and height) of the text in SVG image to avoid clustered text.
The text was updated successfully, but these errors were encountered: