Closed code423n4 closed 2 years ago
The PuttyV2.encodeERC20Assets and PuttyV2.encodeERC721Assets encode an array by feeding the hash generated from the previous iteration to the hash function of current iteration.
This is not true. Ex - the following code from PuttyV2:
function encodeERC20Assets(ERC20Asset[] memory arr) public pure returns (bytes memory encoded) {
for (uint256 i = 0; i < arr.length; i++) {
encoded = abi.encodePacked(
encoded,
// see this line here - the hash from the previous iteration is *not* passed into the hash function
keccak256(abi.encode(ERC20ASSET_TYPE_HASH, arr[i].token, arr[i].tokenAmount))
);
}
}
Agree with sponsor, warden is incorrect in this case. It's doing abi.encodePacked()
, not keccak256
.
Tested in remix to be sure, there isn't a difference. Would have been great for the warden to have done the same before reporting this issue.
Lines of code
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L699
Vulnerability details
Vulnerability Details
From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-encodedata
However, it was observed that the Putty encodes in a way that deviates from the EIP-712 Standard. The
PuttyV2.encodeERC20Assets
andPuttyV2.encodeERC721Assets
encode an array by feeding the hash generated from the previous iteration to the hash function of current iteration.Proof-of-Concept
For example, assume an
erc20Assets
array with three (3) elements. Following is the pseudo code of the encoding function.https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L699
Impact
Hashes generated by Putty does not comply with EIP-712. Thus, the hashes or signatures generated by Putty cannot be parsed by external party since they do not align with the standard, which limit the interoperability of Putty protocol.
Recommended Mitigation Steps
It is recommended to align the encoding scheme with the EIP-712 standard. The array values should be encoded as the
keccak256
hash of the concatenatedencodeData
of their contents/elements.Consider referencing OpenSea's SeaPort implementation of encoding an array according to EIP-712 standard.
_deriveOrderHash
- https://github.com/ProjectOpenSea/seaport/blob/a62c2f8f484784735025d7b03ccb37865bc39e5a/reference/lib/ReferenceGettersAndDerivers.sol#L107_hashOfferItem
- https://github.com/ProjectOpenSea/seaport/blob/a62c2f8f484784735025d7b03ccb37865bc39e5a/reference/lib/ReferenceGettersAndDerivers.sol#L36