Closed c4-submissions closed 9 months ago
We are doing a bit of stretching here to use the RegistryHashes lib to extract the last byte of a bytes32 even when the last byte isn't strictly a registry type but a seaport type, but should still function as desired
0xfoobar (sponsor) disputed
GalloDaSballo marked the issue as unsatisfactory: Insufficient proof
Have asked Warden for POC, will allow until end of Post-Judging QA
For transparency, the judge requested PoC from the warden has been added below:
As explained the decodeType
function, expect a special hash encoded with one of the encoding functions in RegistryHashes
(allHash
, contractHash
, erc721Hash
, erc20Hash
and erc1155Hash
), those functions will add the correct type at the end of the hash (ALL_TYPE
, CONTRACT_TYPE
, ERC721_TYPE
, ERC20_TYPE
and ERC1155_TYPE
).
But in the instances I mentioned in my submission the hash given as input to decodeType
are simple token id returned from seaport (transformed into hashes using bytes32()
), you can check that in the Seaport Docs here.
In my understanding, hashing a simple token id (uint going from 0
to uint256.max
) into bytes32 will not give the same information that are encoded by the RegistryHashes
library hashing functions (mentioned above), and thus in the mentioned instances, the returned hash will not contain the relevant type data in the last bytes that are needed in the logic.
Seaport does allow arbitrary identifierOrCriteria
parameters, but we plan to populate this as a (spoofed CreateOfferer) tokenId, not a hash. So should preserve the trailing byte that we submit. Is there a PoC or modified test case showing that this gets hashed incorrectly to break something? Our test suite is working fine across all types: https://github.com/delegatexyz/delegate-market/blob/main/test/CreateOfferer.t.sol
bytes32 to uint256 doesn't cause a loss of data So to dispute this finding we just have to prove the integrity of the data
We also have empirical proof via the test suite that the code works as intended
I don't believe I have sufficient information to assert that the finding is valid
I have had staff follow up with the Warden and asked them to Produce a Coded POC
When the Warden sent back a few lines, I had staff tell them that they should produce a Coded POC as a necessary requirement to validate finding
I have done my best effort to understand the finding and believe there is insufficient proof to validate it.
Per the tests all Token Identifying data is provided to the contract
This data is "shrunk" into 32bytes for the identified, which is address with one byte replaced with the Token Identifier
Fulfilling of orders is not denied as demonstrated by the Tests as well as POCs I had written for judging other issues
What may be at risk is the possibility of a clash
The clash would fail here due to incorrect create
data
Due to this, I must close the finding as invalid due to lack of proof
This is an example of a finding complex enough where a POC is needed
I would recommend other wardens to consider this idea and follow up with the Sponsor
Lines of code
https://github.com/code-423n4/2023-09-delegate/blob/main/src/libraries/CreateOffererLib.sol#L199-L206 https://github.com/code-423n4/2023-09-delegate/blob/main/src/libraries/CreateOffererLib.sol#L292-L296 https://github.com/code-423n4/2023-09-delegate/blob/main/src/CreateOfferer.sol#L78 https://github.com/code-423n4/2023-09-delegate/blob/main/src/CreateOfferer.sol#L61
Vulnerability details
Impact
The
RegistryHashes.decodeType
function is supposed to take a specificbytes32
hash as input with an encoded token type in the last bytes to know token type is used, but when this function is called in theCreateOffererHelpers
library it is given a simple token Id casted intobytes32
as input which will make the function return a wrong token type (if any) as the given input hasn't the encoded bytes specific to the token type.This issue will cause both
CreateOffererHelpers.updateTransientState
andCreateOffererHelpers.verifyCreate
functions to behave in an undesired manner (or even revert as token type will be wrong) which hinder the process of creating delegate token through theCreateOfferer
contract.Proof of Concept
First let's take a look at the
RegistryHashes.decodeType
here function below :The function basically extract the token type from the last bytes of the given bytes32 input hash
inputHash
, this hash must be encoded with one of the functions :allHash
,contractHash
,erc721Hash
,erc20Hash
anderc1155Hash
and this will give us the five available types (ALL_TYPE
,CONTRACT_TYPE
,ERC721_TYPE
,ERC20_TYPE
andERC1155_TYPE
) declared in theRegistryHashes
library.The issue now is that when the
decodeType
function is called in the functionsCreateOffererHelpers.updateTransientState
andCreateOffererHelpers.verifyCreate
, it is not given a correctly encoded hash as explained above but instead the input to the function is a token id uint casted into bytes32 as highlighted below :updateTransientState
function :The
decodeType
function is givenbytes32(minimumReceived.identifier)
as input even thoughminimumReceived.identifier
is just a simple token id that was given by seaport whengenerateOrder
function was called :This is even explained in the seaport code comments where they indicate that the
identifier
parameter is a token Id (which will be zero in case of ERC20) :verifyCreate
function :The same happens in the
verifyCreate
function where thedecodeType
function is given bytes32 castedidentifier
as input but this parameter is also a simple token id coming from theSpentItem
struct when theratifyOrder
function is called :So in both instances mentioned above the
decodeType
function is not given the correct hash encoded by one of the hashing functions (allHash
,contractHash
,erc721Hash
,erc20Hash
,erc1155Hash
) instead the input is a simple hash that will not contain the token type encoded in its last bytes and thus thedecodeType
function will not return the correct/expected token type in both instances.This will cause problems in both functions as this issue can make the whole process of creating delegate token through
CreateOfferer
revert (DOS) because the decoded token type will be wrong.Tools Used
Manual review
Recommended Mitigation Steps
The
decodeType
function must be given the correctly encoded hash as input in bothCreateOffererHelpers.updateTransientState
andCreateOffererHelpers.verifyCreate
functions.Assessed type
en/de-code