pragma solidity ^0.5.0; import "./GSNBouncerBase.sol"; import "../../cryptography/ECDSA.sol"; /** * @dev A xref:ROOT:gsn-bouncers.adoc#gsn-bouncers[GSN Bouncer] that allows relayed transactions through when they are * accompanied by the signature of a trusted signer. The intent is for this signature to be generated by a server that * performs validations off-chain. Note that nothing is charged to the user in this scheme. Thus, the server should make * sure to account for this in their economic and threat model. */ contract GSNBouncerSignature is GSNBouncerBase { using ECDSA for bytes32; address private _trustedSigner; enum GSNBouncerSignatureErrorCodes { INVALID_SIGNER } /** * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls. */ constructor(address trustedSigner) public { _trustedSigner = trustedSigner; } /** * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN. */ function acceptRelayedCall( address relay, address from, bytes calldata encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes calldata approvalData, uint256 ) external view returns (uint256, bytes memory) { bytes memory blob = abi.encodePacked( relay, from, encodedFunction, transactionFee, gasPrice, gasLimit, nonce, // Prevents replays on RelayHub getHubAddr(), // Prevents replays in multiple RelayHubs address(this) // Prevents replays in multiple recipients ); if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _trustedSigner) { return _approveRelayedCall(); } else { return _rejectRelayedCall(uint256(GSNBouncerSignatureErrorCodes.INVALID_SIGNER)); } } }