Avoid returndatacopy in ERC2771Forwarder by calling via assembly (#4458)

This commit is contained in:
Ernesto García
2023-07-28 18:58:30 -06:00
committed by GitHub
parent 02ea01765a
commit aed5720a01
3 changed files with 117 additions and 17 deletions

View File

@ -7,6 +7,12 @@ import {Context} from "../utils/Context.sol";
/**
* @dev Context variant with ERC2771 support.
*
* WARNING: Avoid using this pattern in contracts that rely in a specific calldata length as they'll
* be affected by any forwarder whose `msg.data` is suffixed with the `from` address according to the ERC2771
* specification adding the address size in bytes (20) to the calldata size. An example of an unexpected
* behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive`
* function only accessible if `msg.data.length == 0`.
*/
abstract contract ERC2771Context is Context {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable

View File

@ -251,11 +251,19 @@ contract ERC2771Forwarder is EIP712, Nonces {
// Nonce should be used before the call to prevent reusing by reentrancy
uint256 currentNonce = _useNonce(signer);
(success, ) = request.to.call{gas: request.gas, value: request.value}(
abi.encodePacked(request.data, request.from)
);
uint256 reqGas = request.gas;
address to = request.to;
uint256 value = request.value;
bytes memory data = abi.encodePacked(request.data, request.from);
_checkForwardedGas(gasleft(), request);
uint256 gasLeft;
assembly {
success := call(reqGas, to, value, add(data, 0x20), mload(data), 0, 0)
gasLeft := gas()
}
_checkForwardedGas(gasLeft, request);
emit ExecutedForwardRequest(signer, currentNonce, success);
}