openzeppelin-contracts icon indicating copy to clipboard operation
openzeppelin-contracts copied to clipboard

`ECDSA.recover()` accepting signature from `calldata`?

Open delaaxe opened this issue 3 years ago • 1 comments

🧐 Motivation

Current ECDSA.recover is accepting a signature typed bytes memory but since signatures are often passed as calldata, adding a method that reads the signature directly from calldata instead of copying to memory could be more gas efficient.

📝 Details

Alternative assembly code reading from calldata without copy:

bytes calldata signature

bytes32 r;
bytes32 s;
uint8 v;
assembly {
    r := calldataload(signature.offset)
    s := calldataload(add(signature.offset, 0x20))
    v := byte(0, calldataload(add(signature.offset, 0x40)))
}

Current code:

bytes memory signature

bytes32 r;
bytes32 s;
uint8 v;
assembly {
    r := mload(add(signature, 0x20))
    s := mload(add(signature, 0x40))
    v := byte(0, mload(add(signature, 0x60)))
}

delaaxe avatar Sep 05 '22 12:09 delaaxe

I'm personally not excited about this. We keep adding variants and having a lot of duplicate code. I'd like to see Solidity allow us to write these functions in a generic way. See https://github.com/ethereum/solidity/issues/13207.

If someone is looking for a gas-efficient way to accept signatures they should not use this function (even with calldata array), instead they should use recover(bytes32 hash, bytes32 r, bytes32 vs).

frangio avatar Sep 05 '22 21:09 frangio