* GSN support Add base Context contract Add GSNContext and tests Add RelayHub deployment to tests Add RelayProvider integration, complete GSNContext tests Switch dependency to openzeppelin-gsn-provider Add default txfee to provider Add basic signing recipient Sign more values Add comment clarifying RelayHub's msg.data Make context constructors internal Rename SigningRecipient to GSNRecipientSignedData Add ERC20Charge recipients Harcode RelayHub address into GSNContext Fix Solidity linter errors Run server from binary, use gsn-helpers to fund it Migrate to published @openzeppelin/gsn-helpers Silence false-positive compiler warning Use GSN helper assertions Rename meta-tx to gsn, take out of drafts Merge ERC20 charge recipients into a single one Rename GSNRecipients to Bouncers Add GSNBouncerUtils to decouple the bouncers from GSNRecipient Add _upgradeRelayHub Store RelayHub address using unstructored storage Add IRelayHub Add _withdrawDeposits to GSNRecipient Add relayHub version to recipient Make _acceptRelayedCall and _declineRelayedCall easier to use Rename GSNBouncerUtils to GSNBouncerBase, make it IRelayRecipient Improve GSNBouncerBase, make pre and post sender-protected and optional Fix GSNBouncerERC20Fee, add tests Add missing GSNBouncerSignature test Override transferFrom in __unstable__ERC20PrimaryAdmin Rhub address slot reduced by 1 Rename relay hub changed event Use released gsn-provider * move gsn to all caps * update to gsn contracts in solidity/master * Adapt for ethereum-package * update gsn related packages * update dependencies to match contracts repo * remove mocha bail option * add changelog entry * add constructors to mocks * use unstructured storage for bouncer implementations
71 lines
2.2 KiB
Solidity
71 lines
2.2 KiB
Solidity
pragma solidity ^0.5.0;
|
|
|
|
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
|
import "./GSNBouncerBase.sol";
|
|
import "../../cryptography/ECDSA.sol";
|
|
|
|
contract GSNBouncerSignature is Initializable, GSNBouncerBase {
|
|
using ECDSA for bytes32;
|
|
|
|
// We use a random storage slot to allow proxy contracts to enable GSN support in an upgrade without changing their
|
|
// storage layout. This value is calculated as: keccak256('gsn.bouncer.signature.trustedSigner'), minus 1.
|
|
bytes32 constant private TRUSTED_SIGNER_STORAGE_SLOT = 0xe7b237a4017a399d277819456dce32c2356236bbc518a6d84a9a8d1cfdf1e9c5;
|
|
|
|
enum GSNBouncerSignatureErrorCodes {
|
|
INVALID_SIGNER
|
|
}
|
|
|
|
function initialize(address trustedSigner) public initializer {
|
|
_setTrustedSigner(trustedSigner);
|
|
}
|
|
|
|
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) == _getTrustedSigner()) {
|
|
return _approveRelayedCall();
|
|
} else {
|
|
return _rejectRelayedCall(uint256(GSNBouncerSignatureErrorCodes.INVALID_SIGNER));
|
|
}
|
|
}
|
|
|
|
function _getTrustedSigner() private view returns (address trustedSigner) {
|
|
bytes32 slot = TRUSTED_SIGNER_STORAGE_SLOT;
|
|
// solhint-disable-next-line no-inline-assembly
|
|
assembly {
|
|
trustedSigner := sload(slot)
|
|
}
|
|
}
|
|
|
|
function _setTrustedSigner(address trustedSigner) private {
|
|
bytes32 slot = TRUSTED_SIGNER_STORAGE_SLOT;
|
|
// solhint-disable-next-line no-inline-assembly
|
|
assembly {
|
|
sstore(slot, trustedSigner)
|
|
}
|
|
}
|
|
}
|