Platform: Code4rena
Start Date: 25/01/2023
Pot Size: $36,500 USDC
Total HM: 11
Participants: 173
Period: 5 days
Judge: kirk-baird
Total Solo HM: 1
Id: 208
League: ETH
Rank: 118/173
Findings: 1
Award: $17.20
π Selected for report: 0
π Solo Findings: 0
π Selected for report: CodingNameKiki
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xAgro, 0xMirce, 0xRobocop, 0xSmartContract, 0xackermann, AkshaySrivastav, ArmedGoose, Aymen0909, BClabs, Breeje, Dewaxindo, Diana, HollaDieWaldfee, IceBear, IllIllI, Iurii3, Josiah, Krayt, PaludoX0, Phenomana, PrasadLak, RaymondFam, Rolezn, SaeedAlipoor01988, SaharDevep, SleepingBugs, adriro, arialblack14, bin2chen, brevis, btk, carlitox477, carrotsmuggler, catellatech, chaduke, chrisdior4, cryptonue, cryptostellar5, csanuragjain, ddimitrov22, fellows, glcanvas, halden, hl_, horsefacts, jat, joestakey, kenta, libratus, lukris02, luxartvinsec, manikantanynala97, martin, matrix_0wl, nadin, nicobevi, oberon, peanuts, prestoncodes, rbserver, sakshamguruji, sashik_eth, sayan, seeu, thekmj, tnevler, trustindistrust, tsvetanovv, xAriextz, zadaru13, zaskoh
17.196 USDC - $17.20
The receipt text is rendered incorrectly.
Here is the code of generateSVG
function (link provided in the Lines of code section above):
// ReceiptRenderer.sol /// @dev generates the on-chain SVG for an ERC-721 token ID /// @param tokenId_ The token id to generate the svg for /// @param questId_ The questId tied to the tokenId /// @return encoded JSON for an SVG image function generateSVG(uint tokenId_, string memory questId_) public pure returns (string memory) { bytes memory svg = abi.encodePacked( '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350">', '<style>.base { fill: white; font-family: serif; font-size: 14px; }</style>', '<rect width="100%" height="100%" fill="black" />', '<text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #', questId_, '</text>', '<text x="70%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #', tokenId_, '</text>', '</svg>' ); return string(abi.encodePacked('data:image/svg+xml;base64,', Base64.encode(svg))); }
It generates an svg
image which will be subsequently part of the receipt, displaying the following two lines of information:
RabbitHole Quest #questId_
RabbitHole Quest Receipt #tokenId_
where the variables questId_
and tokenId_
are placeholders for the actual values.
In order to obtain a clean svg
format, the params passed to abi.encodePacked
can be concatenated into a single string by removing '
and ,
characters as follows:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"> <style>.base { fill: white; font-family: serif; font-size: 14px; }</style> <rect width="100%" height="100%" fill="black" /> <text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #questId_</text> <text x="70%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #tokenId_</text> </svg>
where again the variables questId_
and tokenId_
are placeholders for the actual values.
Then, to check how it actually renders, an online SVG viewer like https://www.svgviewer.dev/ can be utilized.
Here is the respective screenshot:
As can be seen above, the receipt (which is generated on the right hand side), contains two overlapping lines of text.
Manual review.
Online SVG viewer https://www.svgviewer.dev/.
To rectify that, the x
and y
attributes of the text
element shall be modified accordingly. See below a sample proposed modification (the actual values shall be advised by the designer / project team):
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"> <style>.base { fill: white; font-family: serif; font-size: 14px; }</style> <rect width="100%" height="100%" fill="black" /> <text x="50%" y="45%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #questId_</text> <text x="50%" y="55%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #tokenId_</text> </svg>
As a result, the above code renders as:
Accordingly, to achieve the output displayed above, the generateSVG
function shall be modified as shown below:
// ReceiptRenderer.sol /// @dev generates the on-chain SVG for an ERC-721 token ID /// @param tokenId_ The token id to generate the svg for /// @param questId_ The questId tied to the tokenId /// @return encoded JSON for an SVG image function generateSVG(uint tokenId_, string memory questId_) public pure returns (string memory) { bytes memory svg = abi.encodePacked( '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350">', '<style>.base { fill: white; font-family: serif; font-size: 14px; }</style>', '<rect width="100%" height="100%" fill="black" />', // '<text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #', // questId_, // '</text>', '<text x="50%" y="45%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest #', questId_, '</text>', // '<text x="70%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #', // tokenId_, // '</text>', '<text x="50%" y="55%" class="base" dominant-baseline="middle" text-anchor="middle">RabbitHole Quest Receipt #', tokenId_, '</text>', '</svg>' ); return string(abi.encodePacked('data:image/svg+xml;base64,', Base64.encode(svg))); }
Floating pragmas are used in all the contracts. However, the contracts should be deployed with the same compiler version. Locking the pragma helps ensuring that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively.
Reference: https://swcregistry.io/docs/SWC-103
Lock the pragma version: delete pragma solidity ^0.8.15
in favor of pragma solidity 0.8.15
.
public
function visibility, where private
could sufficeThe function generateDataURI
is called only inside the same contract ReceiptRenderer.sol
, therefore, there is no need to assign public
visibility to it, which has higher gas consumption than the private
one.
The function generateDataURI
doesnβt have NatSpec.
indexed
FieldThe event
fields are recommended to be indexed
.
#0 - c4-sponsor
2023-02-08T14:44:06Z
GarrettJMU marked the issue as sponsor confirmed
#1 - c4-judge
2023-02-16T07:30:46Z
kirk-baird marked the issue as grade-b