@@ -13,6 +13,10 @@ import {Context} from "../utils/Context.sol";
1313 * specification adding the address size in bytes (20) to the calldata size. An example of an unexpected
1414 * behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive`
1515 * function only accessible if `msg.data.length == 0`.
16+ *
17+ * WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption.
18+ * Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender}
19+ * recovery.
1620 */
1721abstract contract ERC2771Context is Context {
1822 /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
@@ -48,13 +52,11 @@ abstract contract ERC2771Context is Context {
4852 * a call is not performed by the trusted forwarder or the calldata length is less than
4953 * 20 bytes (an address length).
5054 */
51- function _msgSender () internal view virtual override returns (address sender ) {
52- if (isTrustedForwarder (msg .sender ) && msg .data .length >= 20 ) {
53- // The assembly code is more direct than the Solidity version using `abi.decode`.
54- /// @solidity memory-safe-assembly
55- assembly {
56- sender := shr (96 , calldataload (sub (calldatasize (), 20 )))
57- }
55+ function _msgSender () internal view virtual override returns (address ) {
56+ uint256 calldataLength = msg .data .length ;
57+ uint256 contextSuffixLength = _contextSuffixLength ();
58+ if (isTrustedForwarder (msg .sender ) && calldataLength >= contextSuffixLength) {
59+ return address (bytes20 (msg .data [calldataLength - contextSuffixLength:]));
5860 } else {
5961 return super ._msgSender ();
6062 }
@@ -66,10 +68,19 @@ abstract contract ERC2771Context is Context {
6668 * 20 bytes (an address length).
6769 */
6870 function _msgData () internal view virtual override returns (bytes calldata ) {
69- if (isTrustedForwarder (msg .sender ) && msg .data .length >= 20 ) {
70- return msg .data [:msg .data .length - 20 ];
71+ uint256 calldataLength = msg .data .length ;
72+ uint256 contextSuffixLength = _contextSuffixLength ();
73+ if (isTrustedForwarder (msg .sender ) && calldataLength >= contextSuffixLength) {
74+ return msg .data [:calldataLength - contextSuffixLength];
7175 } else {
7276 return super ._msgData ();
7377 }
7478 }
79+
80+ /**
81+ * @dev ERC-2771 specifies the context as being a single address (20 bytes).
82+ */
83+ function _contextSuffixLength () internal view virtual override returns (uint256 ) {
84+ return 20 ;
85+ }
7586}
0 commit comments