11// SPDX-License-Identifier: MIT
2- // OpenZeppelin Contracts (last updated v5.0.0 ) (metatx/ERC2771Context.sol)
2+ // OpenZeppelin Contracts (last updated v5.0.1 ) (metatx/ERC2771Context.sol)
33
44pragma solidity ^ 0.8.20 ;
55
@@ -14,6 +14,10 @@ import {Initializable} from "../proxy/utils/Initializable.sol";
1414 * specification adding the address size in bytes (20) to the calldata size. An example of an unexpected
1515 * behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive`
1616 * function only accessible if `msg.data.length == 0`.
17+ *
18+ * WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption.
19+ * Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender}
20+ * recovery.
1721 */
1822abstract contract ERC2771ContextUpgradeable is Initializable , ContextUpgradeable {
1923 /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
@@ -49,13 +53,11 @@ abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable
4953 * a call is not performed by the trusted forwarder or the calldata length is less than
5054 * 20 bytes (an address length).
5155 */
52- function _msgSender () internal view virtual override returns (address sender ) {
53- if (isTrustedForwarder (msg .sender ) && msg .data .length >= 20 ) {
54- // The assembly code is more direct than the Solidity version using `abi.decode`.
55- /// @solidity memory-safe-assembly
56- assembly {
57- sender := shr (96 , calldataload (sub (calldatasize (), 20 )))
58- }
56+ function _msgSender () internal view virtual override returns (address ) {
57+ uint256 calldataLength = msg .data .length ;
58+ uint256 contextSuffixLength = _contextSuffixLength ();
59+ if (isTrustedForwarder (msg .sender ) && calldataLength >= contextSuffixLength) {
60+ return address (bytes20 (msg .data [calldataLength - contextSuffixLength:]));
5961 } else {
6062 return super ._msgSender ();
6163 }
@@ -67,10 +69,19 @@ abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable
6769 * 20 bytes (an address length).
6870 */
6971 function _msgData () internal view virtual override returns (bytes calldata ) {
70- if (isTrustedForwarder (msg .sender ) && msg .data .length >= 20 ) {
71- return msg .data [:msg .data .length - 20 ];
72+ uint256 calldataLength = msg .data .length ;
73+ uint256 contextSuffixLength = _contextSuffixLength ();
74+ if (isTrustedForwarder (msg .sender ) && calldataLength >= contextSuffixLength) {
75+ return msg .data [:calldataLength - contextSuffixLength];
7276 } else {
7377 return super ._msgData ();
7478 }
7579 }
80+
81+ /**
82+ * @dev ERC-2771 specifies the context as being a single address (20 bytes).
83+ */
84+ function _contextSuffixLength () internal view virtual override returns (uint256 ) {
85+ return 20 ;
86+ }
7687}
0 commit comments