Files
openzeppelin-contracts/contracts/GSN/bouncers/GSNBouncerSignature.sol
Santiago Palladino 9c4840a479 GSN support (#59)
* 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
2019-08-12 15:28:29 -03:00

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)
}
}
}