// copied from @opengsn/provider-2.2.4, // https://github.com/opengsn/gsn/blob/master/packages/contracts/src/BaseRelayRecipient.sol // for adding `payable` property at the return value of _msgSender() // SPDX-License-Identifier: MIT // solhint-disable no-inline-assembly pragma solidity 0.7.6; import "./IRelayRecipient.sol"; /** * A base contract to be inherited by any contract that want to receive relayed transactions * A subclass must use "_msgSender()" instead of "msg.sender" */ abstract contract BaseRelayRecipient is IRelayRecipient { /* * Forwarder singleton we accept calls from */ address internal _trustedForwarder; // __gap is reserved storage uint256[50] private __gap; event TrustedForwarderUpdated(address trustedForwarder); function getTrustedForwarder() external view returns (address) { return _trustedForwarder; } /// @inheritdoc IRelayRecipient function versionRecipient() external pure override returns (string memory) { return "2.0.0"; } /// @inheritdoc IRelayRecipient function isTrustedForwarder(address forwarder) public view virtual override returns (bool) { return forwarder == _trustedForwarder; } function _setTrustedForwarder(address trustedForwarderArg) internal { _trustedForwarder = trustedForwarderArg; emit TrustedForwarderUpdated(trustedForwarderArg); } /** * return the sender of this call. * if the call came through our trusted forwarder, return the original sender. * otherwise, return `msg.sender`. * should be used in the contract anywhere instead of msg.sender */ /// @inheritdoc IRelayRecipient function _msgSender() internal view virtual override returns (address payable ret) { if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) { // At this point we know that the sender is a trusted forwarder, // so we trust that the last bytes of msg.data are the verified sender address. // extract sender address from the end of msg.data assembly { ret := shr(96, calldataload(sub(calldatasize(), 20))) } } else { ret = msg.sender; } } /** * return the msg.data of this call. * if the call came through our trusted forwarder, then the real sender was appended as the last 20 bytes * of the msg.data - so this method will strip those 20 bytes off. * otherwise (if the call was made directly and not through the forwarder), return `msg.data` * should be used in the contract instead of msg.data, where this difference matters. */ /// @inheritdoc IRelayRecipient function _msgData() internal view virtual override returns (bytes calldata ret) { if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) { return msg.data[0:msg.data.length - 20]; } else { return msg.data; } } }