Skip to content

Commit

Permalink
Unwraps BasePaymaster due to Ownable dep.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 19, 2023
1 parent dde1965 commit 4ef9d74
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 18 deletions.
3 changes: 1 addition & 2 deletions contracts/fast/FastInitFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "../common/lib/LibHasAutomatons.sol";
import "../common/AHasGovernors.sol";
import "../common/AHasMembers.sol";
import "../common/AHasAutomatons.sol";
import "../interfaces/IERC165.sol"; // Interface detection.
import "../interfaces/IERC173.sol"; // Ownership.
import "../interfaces/IDiamondCut.sol"; // Facet management.
import "../interfaces/IDiamondLoupe.sol"; // Facet introspection.
Expand All @@ -21,8 +22,6 @@ import "./lib/LibFastHistory.sol";
import "./lib/LibFastDistributions.sol";
import "./lib/LibFastCrowdfunds.sol";

import "@openzeppelin/contracts/interfaces/IERC165.sol";

/**
* @notice NotAlthough this contract doesn't explicitelly inherit from IERC173, ERC165, IDiamondLoupe etc, all
* methods are in fact implemented by the underlaying Diamond proxy. It is therefore safe to
Expand Down
12 changes: 12 additions & 0 deletions contracts/interfaces/IERC165.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

/// @title ERC165 definition - interface implementation queryability.
interface IERC165 {
/// @notice Queries if a contract implements an interface
/// @param interfaceId The interface identifier, as specified in ERC165.
/// @notice Interface identification is specified in ERC-165. This method uses less than 30,000 gas.
/// @return A `bool` set to `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff.
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
3 changes: 1 addition & 2 deletions contracts/issuer/IssuerInitFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.10;

import "../common/AHasMembers.sol";
import "../common/AHasAutomatons.sol";
import "../interfaces/IERC165.sol"; // Interface detection.
import "../interfaces/IERC173.sol"; // Ownership.
import "../interfaces/IDiamondCut.sol"; // Facet management.
import "../interfaces/IDiamondLoupe.sol"; // Facet introspection.
Expand All @@ -13,8 +14,6 @@ import "./lib/AIssuerFacet.sol";
import "./lib/LibIssuer.sol";
import "./lib/LibIssuerAccess.sol";

import "@openzeppelin/contracts/interfaces/IERC165.sol";

/**
* @title The Issuer Smart Contract.
* @notice The marketplace contract is in charge of keeping track of marketplace members and has logic
Expand Down
3 changes: 1 addition & 2 deletions contracts/marketplace/MarketplaceInitFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "../common/lib/LibHasForwarder.sol";
import "../common/AHasMembers.sol";
import "../common/AHasAutomatons.sol";
import "../common/AHasForwarder.sol";
import "../interfaces/IERC165.sol"; // Interface detection.
import "../interfaces/IERC173.sol"; // Ownership.
import "../interfaces/IDiamondCut.sol"; // Facet management.
import "../interfaces/IDiamondLoupe.sol"; // Facet introspection.
Expand All @@ -17,8 +18,6 @@ import "./lib/LibMarketplace.sol";
import "./lib/LibMarketplaceAccess.sol";
import "./lib/LibMarketplaceTokenHolders.sol";

import "@openzeppelin/contracts/interfaces/IERC165.sol";

/// @notice The Marketplace initialization facet.
contract MarketplaceInitFacet is AMarketplaceFacet {
/// Initializers.
Expand Down
3 changes: 1 addition & 2 deletions contracts/paymaster/PaymasterInitFacet.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../interfaces/IERC165.sol"; // Interface detection.
import "../interfaces/IERC173.sol"; // Ownership.
import "../interfaces/IDiamondCut.sol"; // Facet management.
import "../interfaces/IDiamondLoupe.sol"; // Facet introspection.
Expand All @@ -9,8 +10,6 @@ import "../lib/LibDiamond.sol";
import "./lib/APaymasterFacet.sol";
import "./lib/LibPaymaster.sol";

import "@openzeppelin/contracts/interfaces/IERC165.sol";

/// @notice The Paymaster initialization facet.
contract PaymasterInitFacet is APaymasterFacet {
/// Initializers.
Expand Down
143 changes: 138 additions & 5 deletions contracts/paymaster/PaymasterTopFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,131 @@ pragma solidity 0.8.10;
import "./lib/LibPaymaster.sol";
import "./lib/APaymasterFacet.sol";

import "@opengsn/contracts/src/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 APaymasterFacet, BasePaymaster {
bool public useRejectOnRecipientRevert = false;

// TODO: Do we use the Marketplace at this point to check that the sender is allowed?
Expand All @@ -15,24 +137,35 @@ contract PaymasterTopFacet is APaymasterFacet, BasePaymaster {
bytes calldata signature,
bytes calldata approvalData,
uint256 maxPossibleGas
) internal virtual override returns (bytes memory context, bool revertOnRecipientRevert) {
) internal 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 virtual override {
) internal {
(context, success, gasUseWithoutPost, relayData);
}

function versionPaymaster() external view virtual override returns (string memory) {
function versionPaymaster() external view returns (string memory) {
return "3.0.0-beta.3+opengsn.accepteverything.ipaymaster";
}
}
6 changes: 1 addition & 5 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ const config: HardhatUserConfig = {
["Facet$", "RequiresFastContractCaller()"],
]),
include: [
"IERC165",
"IERC173",
"IDiamondCut",
"IDiamondLoupe",
Expand All @@ -76,7 +75,6 @@ const config: HardhatUserConfig = {
["Facet$", "RequiresMarketplaceMembership(address)"],
]),
include: [
"IERC165",
"IERC173",
"IDiamondCut",
"IDiamondLoupe",
Expand Down Expand Up @@ -115,7 +113,6 @@ const config: HardhatUserConfig = {
["Facet$", "InvalidCrowdfundBasisPointFee(uint32)"],
]),
include: [
"IERC165",
"IERC173",
"IDiamondCut",
"IDiamondLoupe",
Expand All @@ -133,8 +130,7 @@ const config: HardhatUserConfig = {
["Facet$", "InvalidPaymasterDataLength()"],
]),
include: [
// "IERC165",
// "IERC173",
"IERC173",
"IDiamondCut",
"IDiamondLoupe",
...PAYMASTER_FACETS,
Expand Down
3 changes: 3 additions & 0 deletions tasks/paymaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ const deployPaymaster = async (
},
deterministicSalt: deploymentSalt(hre),
log: true,
excludeSelectors: {
"PaymasterTopFacet": ["supportsInterface"]
}
});
}
// Return a handle to the diamond.
Expand Down

0 comments on commit 4ef9d74

Please sign in to comment.