12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)
- pragma solidity ^0.8.20;
- 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
- address private immutable _trustedForwarder;
- /// @custom:oz-upgrades-unsafe-allow constructor
- constructor(address trustedForwarder) {
- _trustedForwarder = trustedForwarder;
- }
- function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
- return forwarder == _trustedForwarder;
- }
- function _msgSender() internal view virtual override returns (address sender) {
- if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
- // The assembly code is more direct than the Solidity version using `abi.decode`.
- /// @solidity memory-safe-assembly
- assembly {
- sender := shr(96, calldataload(sub(calldatasize(), 20)))
- }
- } else {
- return super._msgSender();
- }
- }
- function _msgData() internal view virtual override returns (bytes calldata) {
- if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
- return msg.data[:msg.data.length - 20];
- } else {
- return super._msgData();
- }
- }
- }
|