tokenbridge-contracts/contracts/gsn/BaseRelayRecipient.sol

58 lines
2.3 KiB
Solidity

// SPDX-License-Identifier:MIT
// solhint-disable no-inline-assembly
pragma solidity 0.4.24;
import "./interfaces/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"
*/
contract BaseRelayRecipient is IRelayRecipient {
/**
* 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
*/
function _msgSender() internal view returns (address ret) {
if (msg.data.length >= 24 && 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 {
return 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, return `msg.data`
* should be used in the contract instead of msg.data, where the difference matters (e.g. when explicitly
* signing or hashing the
*/
function _msgData() internal view returns (bytes memory ret) {
if (msg.data.length >= 24 && isTrustedForwarder(msg.sender)) {
// At this point we know that the sender is a trusted forwarder,
// we copy the msg.data , except the last 20 bytes (and update the total length)
assembly {
let ptr := mload(0x40)
// copy only size-20 bytes
let size := sub(calldatasize, 20)
// structure RLP data as <offset> <length> <bytes>
mstore(ptr, 0x20)
mstore(add(ptr, 32), size)
calldatacopy(add(ptr, 64), 0, size)
return(ptr, add(size, 64))
}
} else {
return msg.data;
}
}
}