Platform: Code4rena
Start Date: 17/03/2023
Pot Size: $36,500 USDC
Total HM: 10
Participants: 98
Period: 3 days
Judge: leastwood
Total Solo HM: 5
Id: 223
League: ETH
Rank: 12/98
Findings: 1
Award: $401.03
🌟 Selected for report: 0
🚀 Solo Findings: 0
401.0269 USDC - $401.03
The fuse()
function in Namespace.sol
incorrectly calculates fused bytes. The first parameter to the characterToUnicodeBytes()
function is font class, which is always set to 0. This leads to an incorrect calculation of the tokenToName
value, resulting in a bunch of emojis instead of the expected characters. For example, a list of tiles with characters b, 9, 😪, 𝓇, 8, 😮, 𝔢 will become ✅🤔😪😂🎂😮☕ instead of b9😪𝓇8😮𝔢.
This is a high severity issue as it can create incorrect associations in the nameToToken and tokenToName mappings, leading to various issues. The main goal of Namespace contract is to able to fuse tiles and generate name from the tile's character. fuse()
function fails due to this bug.
bytes memory charAsBytes = Utils.characterToUnicodeBytes(0, tileData.characterIndex, characterModifier);
This issue can easily be verified using the below foundry test. First, create a tray with tokenId
1 as an owner. Then, fuse all the tiles in that tray. The expected output name is b9😪𝓇8😮𝔢, but due to this bug, the output is a bunch of emojis ✅🤔😪😂🎂😮☕ . Basically any character that is not an emoji is lost.
function testPoc() public { vm.startPrank(owner); tray.buy(1); assertEq(tray.balanceOf(owner), 1); note.approve(address(ns), type(uint256).max); ns.fuse(buildCharacters(1)); // first Tray generates tiles with b, 9, 😪, 𝓇, 8, 😮, 𝔢 // after fusing it the name should be b9😪𝓇8😮𝔢 string memory expectedName = unicode"b9😪𝓇8😮𝔢"; // assertion fails assertEq(ns.tokenToName(1), expectedName); vm.stopPrank(); }
.... .... .... ├─ [1088] Namespace::tokenToName(1) [staticcall] │ └─ ← ✅🤔😪😂🎂😮☕ ├─ emit log(: Error: a == b not satisfied [string]) ├─ emit log_named_string(key: Value a, val: ✅🤔😪😂🎂😮☕) ├─ emit log_named_string(key: Value b, val: b9😪𝓇8😮𝔢) ├─ [0] VM::stopPrank() │ └─ ← () └─ ← () Test result: FAILED. 0 passed; 1 failed; finished in 8.26ms Failing tests: Encountered 1 failing test in src/test/Namespace.t.sol:NamespaceTest [FAIL. Reason: Assertion failed.] testPoc() (gas: 593578)
Manual.
The fix is very simple. When converting a character to Unicode bytes, make sure to pass the font class of the tile as shown below:
- bytes memory charAsBytes = Utils.characterToUnicodeBytes(0, tileData.characterIndex, characterModifier); + bytes memory charAsBytes = Utils.characterToUnicodeBytes(tileData.fontClass, tileData.characterIndex, characterModifier);
#0 - c4-judge
2023-03-28T22:01:35Z
0xleastwood marked the issue as duplicate of #117
#1 - c4-judge
2023-04-11T19:29:02Z
0xleastwood marked the issue as satisfactory