transmissions11/solmate

Purpose of checking if `returndatasize` is greater than 31 bytes in `SafeTransferLib`?

xenide opened this issue · 4 comments

xenide commented

I'm curious regarding the purpose of checking for the return size being greater than 31 bytes. Is it to guard against implementations returning a uint8 / uint128 etc types instead of a bool?

Besides, it doesn't guard against implementations which return a uint256 type but of value 1 does it?

For context, I had this question after referencing solady's implementation, which doesn't check for the return type greater than 31 bytes.

@xenide Solady's implementation does indeed check that the returndatasize is greater than 31, albeit with some devious trickery.

In all the examples, as all the call function selectors does not end with the 0x01 byte, simply checking that slot 0x00 is rewritten to 0x0000000000000000000000000000000000000000000000000000000000000001 (i.e. 1) is sufficient to check that the returndatasize is indeed greater than 31.

xenide commented

got it, but both of these implementations don't really protect against an ERC20 that returns a uint8 or uint16 for example, if the contract is written using solidity.

If the contract was using assembly or yul then it's possible to return less than 32 bytes. Correct?

@xenide It is possible to return less than 32 bytes if you write in assembly. But then, this will result in memory slot 0x00 not being exactly 1.

xenide commented

So to circle back to the original question, the purpose of checking for return data size greater than 31 bytes is really to guard against weird implementations in assembly/yul which returns types less than 32 bytes. It does not guard against solidity implementations returning a 1 in int/uint/bool

Is my understanding correct? If so, I'll close this issue