Skip to content

Commit

Permalink
Refactors file locations for BasePaymaster.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 24, 2023
1 parent a4797ed commit 173f7b1
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 139 deletions.
167 changes: 167 additions & 0 deletions contracts/paymaster/BasePaymaster.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// SPDX-License-Identifier: GPL-3.0-only
// COPIED FROM: https://github.com/opengsn/gsn/blob/master/packages/contracts/src/BasePaymaster.sol
// Changes:
// - Drops Ownable (OpenZeppelin).
pragma solidity 0.8.10;

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

import "@opengsn/contracts/src/interfaces/IPaymaster.sol";
import "@opengsn/contracts/src/interfaces/IRelayHub.sol";
import "@opengsn/contracts/src/forwarder/IForwarder.sol";
import "@opengsn/contracts/src/utils/GsnEip712Library.sol";

/**
* @notice An abstract base class to be inherited by a concrete Paymaster.
* A subclass must implement:
* - preRelayedCall
* - postRelayedCall
*/
abstract contract BasePaymaster is IPaymaster, ERC165 {
using ERC165Checker for address;

IRelayHub internal relayHub;
address private _trustedForwarder;

/// @inheritdoc IPaymaster
function getRelayHub() public view override returns (address) {
return address(relayHub);
}

//overhead of forwarder verify+signature, plus hub overhead.
uint256 public constant FORWARDER_HUB_OVERHEAD = 50000;

//These parameters are documented in IPaymaster.GasAndDataLimits
uint256 public constant PRE_RELAYED_CALL_GAS_LIMIT = 100000;
uint256 public constant POST_RELAYED_CALL_GAS_LIMIT = 110000;
uint256 public constant PAYMASTER_ACCEPTANCE_BUDGET = PRE_RELAYED_CALL_GAS_LIMIT + FORWARDER_HUB_OVERHEAD;
uint256 public constant CALLDATA_SIZE_LIMIT = 10500;

/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IPaymaster).interfaceId || super.supportsInterface(interfaceId);
}

/// @inheritdoc IPaymaster
function getGasAndDataLimits() public view virtual override returns (IPaymaster.GasAndDataLimits memory limits) {
return
IPaymaster.GasAndDataLimits(
PAYMASTER_ACCEPTANCE_BUDGET,
PRE_RELAYED_CALL_GAS_LIMIT,
POST_RELAYED_CALL_GAS_LIMIT,
CALLDATA_SIZE_LIMIT
);
}

/**
* @notice this method must be called from preRelayedCall to validate that the forwarder
* is approved by the paymaster as well as by the recipient contract.
*/
function _verifyForwarder(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(getTrustedForwarder() == relayRequest.relayData.forwarder, "Forwarder is not trusted");
GsnEip712Library.verifyForwarderTrusted(relayRequest);
}

function _verifyRelayHubOnly() internal view virtual {
require(msg.sender == getRelayHub(), "can only be called by RelayHub");
}

function _verifyValue(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(relayRequest.request.value == 0, "value transfer not supported");
}

function _verifyPaymasterData(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(relayRequest.relayData.paymasterData.length == 0, "should have no paymasterData");
}

function _verifyApprovalData(bytes calldata approvalData) internal view virtual {
require(approvalData.length == 0, "should have no approvalData");
}

/**
* @notice The owner of the Paymaster can change the instance of the RelayHub this Paymaster works with.
* :warning: **Warning** :warning: The deposit on the previous RelayHub must be withdrawn first.
*/
// ONLY OWNER
function setRelayHub(IRelayHub hub) public {
require(address(hub).supportsInterface(type(IRelayHub).interfaceId), "target is not a valid IRelayHub");
relayHub = hub;
}

/**
* @notice The owner of the Paymaster can change the instance of the Forwarder this Paymaster works with.
* @notice the Recipients must trust this Forwarder as well in order for the configuration to remain functional.
*/
// ONLY OWNER
function setTrustedForwarder(address forwarder) public virtual {
require(forwarder.supportsInterface(type(IForwarder).interfaceId), "target is not a valid IForwarder");
_trustedForwarder = forwarder;
}

function getTrustedForwarder() public view virtual override returns (address) {
return _trustedForwarder;
}

/**
* @notice Any native Ether transferred into the paymaster is transferred as a deposit to the RelayHub.
* This way, we don't need to understand the RelayHub API in order to replenish the paymaster.
*/
receive() external payable virtual {
require(address(relayHub) != address(0), "relay hub address not set");
relayHub.depositFor{value: msg.value}(address(this));
}

/**
* @notice Withdraw deposit from the RelayHub.
* @param amount The amount to be subtracted from the sender.
* @param target The target to which the amount will be transferred.
*/
// ONLY OWNER
function withdrawRelayHubDepositTo(uint256 amount, address payable target) public {
relayHub.withdraw(target, amount);
}

/// @inheritdoc IPaymaster
function preRelayedCall(
GsnTypes.RelayRequest calldata relayRequest,
bytes calldata signature,
bytes calldata approvalData,
uint256 maxPossibleGas
) external override returns (bytes memory, bool) {
_verifyRelayHubOnly();
_verifyForwarder(relayRequest);
_verifyValue(relayRequest);
_verifyPaymasterData(relayRequest);
_verifyApprovalData(approvalData);
return _preRelayedCall(relayRequest, signature, approvalData, maxPossibleGas);
}

/**
* @notice internal logic the paymasters need to provide to select which transactions they are willing to pay for
* @notice see the documentation for `IPaymaster::preRelayedCall` for details
*/
function _preRelayedCall(
GsnTypes.RelayRequest calldata,
bytes calldata,
bytes calldata,
uint256
) internal virtual returns (bytes memory, bool);

/// @inheritdoc IPaymaster
function postRelayedCall(
bytes calldata context,
bool success,
uint256 gasUseWithoutPost,
GsnTypes.RelayData calldata relayData
) external override {
_verifyRelayHubOnly();
_postRelayedCall(context, success, gasUseWithoutPost, relayData);
}

/**
* @notice internal logic the paymasters need to provide if they need to take some action after the transaction
* @notice see the documentation for `IPaymaster::postRelayedCall` for details
*/
function _postRelayedCall(bytes calldata, bool, uint256, GsnTypes.RelayData calldata) internal virtual;
}
144 changes: 5 additions & 139 deletions contracts/paymaster/PaymasterTopFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,132 +3,9 @@ pragma solidity 0.8.10;

import "./lib/LibPaymaster.sol";
import "./lib/APaymasterFacet.sol";
import "./BasePaymaster.sol";

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

import "@opengsn/contracts/src/interfaces/IPaymaster.sol";
import "@opengsn/contracts/src/interfaces/IRelayHub.sol";
import "@opengsn/contracts/src/forwarder/IForwarder.sol";
import "@opengsn/contracts/src/utils/GsnEip712Library.sol";

contract PaymasterTopFacet is APaymasterFacet, IPaymaster {
using ERC165Checker for address;

IRelayHub internal relayHub;
address private _trustedForwarder;

/// @inheritdoc IPaymaster
function getRelayHub() public view returns (address) {
return address(relayHub);
}

//overhead of forwarder verify+signature, plus hub overhead.
uint256 public constant FORWARDER_HUB_OVERHEAD = 50000;

//These parameters are documented in IPaymaster.GasAndDataLimits
uint256 public constant PRE_RELAYED_CALL_GAS_LIMIT = 100000;
uint256 public constant POST_RELAYED_CALL_GAS_LIMIT = 110000;
uint256 public constant PAYMASTER_ACCEPTANCE_BUDGET = PRE_RELAYED_CALL_GAS_LIMIT + FORWARDER_HUB_OVERHEAD;
uint256 public constant CALLDATA_SIZE_LIMIT = 10500;

/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IPaymaster).interfaceId;
}

/// @inheritdoc IPaymaster
function getGasAndDataLimits() public view virtual returns (IPaymaster.GasAndDataLimits memory limits) {
return
IPaymaster.GasAndDataLimits(
PAYMASTER_ACCEPTANCE_BUDGET,
PRE_RELAYED_CALL_GAS_LIMIT,
POST_RELAYED_CALL_GAS_LIMIT,
CALLDATA_SIZE_LIMIT
);
}

/**
* @notice this method must be called from preRelayedCall to validate that the forwarder
* is approved by the paymaster as well as by the recipient contract.
*/
function _verifyForwarder(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(getTrustedForwarder() == relayRequest.relayData.forwarder, "Forwarder is not trusted");
GsnEip712Library.verifyForwarderTrusted(relayRequest);
}

function _verifyRelayHubOnly() internal view virtual {
require(msg.sender == getRelayHub(), "can only be called by RelayHub");
}

function _verifyValue(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(relayRequest.request.value == 0, "value transfer not supported");
}

function _verifyPaymasterData(GsnTypes.RelayRequest calldata relayRequest) internal view virtual {
require(relayRequest.relayData.paymasterData.length == 0, "should have no paymasterData");
}

function _verifyApprovalData(bytes calldata approvalData) internal view virtual {
require(approvalData.length == 0, "should have no approvalData");
}

/**
* @notice The owner of the Paymaster can change the instance of the RelayHub this Paymaster works with.
* :warning: **Warning** :warning: The deposit on the previous RelayHub must be withdrawn first.
*/
function setRelayHub(IRelayHub hub) public {
require(address(hub).supportsInterface(type(IRelayHub).interfaceId), "target is not a valid IRelayHub");
relayHub = hub;
}

/**
* @notice The owner of the Paymaster can change the instance of the Forwarder this Paymaster works with.
* @notice the Recipients must trust this Forwarder as well in order for the configuration to remain functional.
*/
function setTrustedForwarder(address forwarder) public virtual {
require(forwarder.supportsInterface(type(IForwarder).interfaceId), "target is not a valid IForwarder");
_trustedForwarder = forwarder;
}

function getTrustedForwarder() public view virtual returns (address) {
return _trustedForwarder;
}

/**
* @notice Any native Ether transferred into the paymaster is transferred as a deposit to the RelayHub.
* This way, we don't need to understand the RelayHub API in order to replenish the paymaster.
*/
receive() external payable virtual {
require(address(relayHub) != address(0), "relay hub address not set");
relayHub.depositFor{value: msg.value}(address(this));
}

/**
* @notice Withdraw deposit from the RelayHub.
* @param amount The amount to be subtracted from the sender.
* @param target The target to which the amount will be transferred.
*/
function withdrawRelayHubDepositTo(uint256 amount, address payable target) public {
relayHub.withdraw(target, amount);
}

/// @inheritdoc IPaymaster
function preRelayedCall(
GsnTypes.RelayRequest calldata relayRequest,
bytes calldata signature,
bytes calldata approvalData,
uint256 maxPossibleGas
) external returns (bytes memory, bool) {
_verifyRelayHubOnly();
_verifyForwarder(relayRequest);
_verifyValue(relayRequest);
_verifyPaymasterData(relayRequest);
_verifyApprovalData(approvalData);
return _preRelayedCall(relayRequest, signature, approvalData, maxPossibleGas);
}

///// OLD SHIZZLE /////

contract PaymasterTopFacet is BasePaymaster {
bool public useRejectOnRecipientRevert = false;

// TODO: Do we use the Marketplace at this point to check that the sender is allowed?
Expand All @@ -137,35 +14,24 @@ contract PaymasterTopFacet is APaymasterFacet, IPaymaster {
bytes calldata signature,
bytes calldata approvalData,
uint256 maxPossibleGas
) internal returns (bytes memory context, bool revertOnRecipientRevert) {
) internal virtual override returns (bytes memory context, bool revertOnRecipientRevert) {
(signature, maxPossibleGas);
if (approvalData.length == 0) revert ICustomErrors.InvalidApprovalDataLength();
if (relayRequest.relayData.paymasterData.length == 0) revert ICustomErrors.InvalidPaymasterDataLength();

return ("", useRejectOnRecipientRevert);
}

/// @inheritdoc IPaymaster
function postRelayedCall(
bytes calldata context,
bool success,
uint256 gasUseWithoutPost,
GsnTypes.RelayData calldata relayData
) external {
_verifyRelayHubOnly();
_postRelayedCall(context, success, gasUseWithoutPost, relayData);
}

function _postRelayedCall(
bytes calldata context,
bool success,
uint256 gasUseWithoutPost,
GsnTypes.RelayData calldata relayData
) internal {
) internal virtual override {
(context, success, gasUseWithoutPost, relayData);
}

function versionPaymaster() external view returns (string memory) {
function versionPaymaster() external view override returns (string memory) {
return "3.0.0-beta.3+opengsn.accepteverything.ipaymaster";
}
}

0 comments on commit 173f7b1

Please sign in to comment.