Skip to content

Commit

Permalink
very wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 12, 2023
1 parent beb5ed5 commit 1cd22ab
Show file tree
Hide file tree
Showing 12 changed files with 265 additions and 6 deletions.
17 changes: 14 additions & 3 deletions contracts/common/AHasAutomatons.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ pragma solidity 0.8.10;
import "../lib/LibAddressSet.sol";
import "../lib/LibPaginate.sol";
import "../common/lib/LibHasAutomatons.sol";
import "@opengsn/contracts/src/ERC2771Recipient.sol";

/**
* @title The Fast Smart Contract.
* @notice The Fast Automatons abstract contract is in charge of keeping track of automaton accounts.
*/
abstract contract AHasAutomatons {
abstract contract AHasAutomatons is ERC2771Recipient {
using LibAddressSet for LibAddressSet.Data;

/// Errors.
Expand Down Expand Up @@ -88,7 +89,7 @@ abstract contract AHasAutomatons {
* @param candidate is the automaton address to which the privileges should be assigned.
* @param privileges is a bitfield of privileges to apply.
*/
function setAutomatonPrivileges(address candidate, uint32 privileges) external onlyAutomatonManager(msg.sender) {
function setAutomatonPrivileges(address candidate, uint32 privileges) external onlyAutomatonManager(_msgSender()) {
LibHasAutomatons.Data storage ds = LibHasAutomatons.data();
ds.automatonSet.add(candidate, true);
ds.automatonPrivileges[candidate] = privileges;
Expand All @@ -99,13 +100,23 @@ abstract contract AHasAutomatons {
* @notice Removes an automaton completely.
* @param candidate is the automaton to remove.
*/
function removeAutomaton(address candidate) external onlyAutomatonManager(msg.sender) {
function removeAutomaton(address candidate) external onlyAutomatonManager(_msgSender()) {
LibHasAutomatons.Data storage ds = LibHasAutomatons.data();
ds.automatonSet.remove(candidate, false);
delete ds.automatonPrivileges[candidate];
emit AutomatonRemoved(candidate);
}

/**
* @notice ERC2771Recipient stuff...
* FIX THE MODIFIER GUARD!!!!!!!!!!!!!!!!!!!!!!
*/
function setTrustedForwarder(address forwarder) external onlyAutomatonManager(_msgSender()) {
LibHasAutomatons.Data storage ds = LibHasAutomatons.data();
ds.trustedForwarder = forwarder;
_setTrustedForwarder(forwarder);
}

/// Modifiers.

modifier onlyAutomatonManager(address who) {
Expand Down
2 changes: 2 additions & 0 deletions contracts/common/lib/LibHasAutomatons.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ library LibHasAutomatons {
LibAddressSet.Data automatonSet;
/// @notice This is where we store privileges for each of our automaton account.
mapping(address => uint32) automatonPrivileges;
/// @notice This is where we store the trusted forwarder.
address trustedForwarder;
}

function data() internal pure returns (Data storage s) {
Expand Down
2 changes: 2 additions & 0 deletions contracts/marketplace/MarketplaceInitFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ contract MarketplaceInitFacet is AMarketplaceFacet {

struct InitializerParams {
address issuer;
address trustedForwarder;
}

function initialize(InitializerParams calldata params) external onlyDeployer {
Expand Down Expand Up @@ -61,5 +62,6 @@ contract MarketplaceInitFacet is AMarketplaceFacet {

// Initialize automatons storage.
LibHasAutomatons.data().version = LibHasAutomatons.STORAGE_VERSION;
LibHasAutomatons.data().trustedForwarder = params.trustedForwarder;
}
}
2 changes: 0 additions & 2 deletions contracts/marketplace/lib/LibMarketplace.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../../lib/LibAddressSet.sol";

library LibMarketplace {
// The current version of the storage.
uint16 internal constant STORAGE_VERSION = 1;
Expand Down
43 changes: 43 additions & 0 deletions contracts/paymaster/PaymasterInitFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../common/lib/LibHasMembers.sol";
import "../common/lib/LibHasAutomatons.sol";
import "../common/AHasMembers.sol";
import "../common/AHasAutomatons.sol";
import "../interfaces/IERC165.sol"; // Interface Support.
import "../interfaces/IERC173.sol"; // Ownership.
import "../interfaces/IDiamondCut.sol"; // Facet management.
import "../interfaces/IDiamondLoupe.sol"; // Facet introspection.
import "../interfaces/ICustomErrors.sol";
import "../lib/LibDiamond.sol";
import "./lib/APaymasterFacet.sol";
import "./lib/LibPaymaster.sol";

/// @notice The Paymaster initialization facet.
contract PaymasterInitFacet is APaymasterFacet {
/// Initializers.

struct InitializerParams {
address issuer;
}

function initialize(InitializerParams calldata params) external onlyDeployer {
// Make sure we haven't initialized yet.
if (LibPaymaster.data().version >= LibPaymaster.STORAGE_VERSION) revert ICustomErrors.AlreadyInitialized();

// Register interfaces.
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
ds.supportedInterfaces[type(IERC165).interfaceId] = true;
ds.supportedInterfaces[type(IERC173).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;

// ------------------------------------- //

// Initialize top-level storage.
LibPaymaster.Data storage topData = LibPaymaster.data();
topData.version = LibPaymaster.STORAGE_VERSION;
topData.issuer = params.issuer;
}
}
38 changes: 38 additions & 0 deletions contracts/paymaster/PaymasterTopFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "./lib/LibPaymaster.sol";
import "./lib/APaymasterFacet.sol";
import "@opengsn/contracts/src/BasePaymaster.sol";

contract PaymasterFacet is APaymasterFacet, BasePaymaster {
bool public useRejectOnRecipientRevert = false;

/// TODO: MAKE THESE ERROR... SUPERNICE™
function _preRelayedCall(
GsnTypes.RelayRequest calldata relayRequest,
bytes calldata signature,
bytes calldata approvalData,
uint256 maxPossibleGas
) internal virtual override returns (bytes memory context, bool revertOnRecipientRevert) {
(signature, maxPossibleGas);
require(approvalData.length == 0, "approvalData: invalid length");
require(relayRequest.relayData.paymasterData.length == 0, "paymasterData: invalid length");

return ("", useRejectOnRecipientRevert);
}

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

// TODO: Setter and be in lib data....
function versionPaymaster() external view virtual override returns (string memory) {
return "3.0.0-beta.3+opengsn.tokensphere.ipaymaster";
}
}
27 changes: 27 additions & 0 deletions contracts/paymaster/lib/APaymasterFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../../lib/LibHelpers.sol";
import "../../common/AHasMembers.sol";
import "../../interfaces/ICustomErrors.sol";
import "../lib/LibPaymaster.sol";

/**
* @notice This contract is a group of modifiers that can be used by any Paymaster facets to guard against
* certain permissions.
*/
abstract contract APaymasterFacet {
/// Internal ACL functions.

// function _isIssuerMember(address who) internal view returns (bool) {
// return AHasMembers(LibPaymaster.data().issuer).isMember(who);
// }

// Modifiers.

/// @notice Ensures that a method can only be called by the singleton deployer contract factory.
modifier onlyDeployer() virtual {
if (!LibHelpers._isDeployer(msg.sender)) revert ICustomErrors.InternalMethod();
_;
}
}
22 changes: 22 additions & 0 deletions contracts/paymaster/lib/LibPaymaster.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

library LibPaymaster {
// The current version of the storage.
uint16 internal constant STORAGE_VERSION = 1;
// This is keccak256('Paymaster.storage'):
bytes32 internal constant STORAGE_SLOT = 0x8f0e66ee30211ca069424cd4b533ee66f04c45421216c1a6601cf23359c1f7f8;

struct Data {
/// @notice The latest intializer version that was called.
uint16 version;
/// @notice The internal pointer to the Issuer contract.
address issuer;
}

function data() internal pure returns (Data storage s) {
assembly {
s.slot := STORAGE_SLOT
}
}
}
12 changes: 12 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DEPLOYER_FACTORY_COMMON, accounts, abiFilter } from "./src/utils";
import { ISSUER_FACETS } from "./tasks/issuer";
import { MARKETPLACE_FACETS } from "./tasks/marketplace";
import { FAST_FACETS } from "./tasks/fast";
import { PAYMASTER_FACETS } from "./tasks/paymaster";

// Import all of our tasks here!
import "./tasks/accounts";
Expand Down Expand Up @@ -121,6 +122,17 @@ const config: HardhatUserConfig = {
...FAST_FACETS,
],
},
{
name: "Paymaster",
filter: abiFilter([]),
include: [
"IERC165",
"IERC173",
"IDiamondCut",
"IDiamondLoupe",
...PAYMASTER_FACETS,
],
},
],
networks: {
// Built-in for tests etc.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"dependencies": {
"@openzeppelin/contracts": "^4.9.2",
"@opengsn/contracts": "^3.0.0-beta.6",
"@typechain/ethers-v5": "^11.1.1",
"@typechain/hardhat": "^9.0.0",
"ethers": "^5.7.2",
Expand Down
96 changes: 96 additions & 0 deletions tasks/paymaster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { task } from "hardhat/config";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { parseEther } from "ethers/lib/utils";
import { deploymentSalt } from "../src/utils";
import { Paymaster } from "../typechain/hardhat-diamond-abi/HardhatDiamondABI.sol";

// Tasks.

interface PaymasterDeployParams { }

task("paymaster-deploy", "Deploys the main Paymaster contract").setAction(
async (_params: PaymasterDeployParams, hre) => {
const { address: issuerAddr } = await hre.deployments.get("Issuer");
await deployPaymaster(hre, issuerAddr);
}
);

interface PaymasterUpdateFacetsParams { }

task("paymaster-update-facets", "Updates facets of our Paymaster")
.setAction(async (_params: PaymasterUpdateFacetsParams, hre) => {
const { deployments, getNamedAccounts } = hre;
const { deployer } = await getNamedAccounts();
// Make sure that the fast is known from our tooling.
const { address } = await deployments.get("Paymaster");
console.log(`Updating paymaster diamond facets at ${address}...`);
await deployments.diamond.deploy("Paymaster", {
from: deployer,
facets: PAYMASTER_FACETS,
deterministicSalt: deploymentSalt(hre),
log: true,
});
});


interface PaymasterFundParams { }

task("paymaster-fund", "Funds the Paymaster")
.setAction(async (_params: PaymasterFundParams, hre) => {
const { deployments, getNamedAccounts } = hre;
// Who will juice it?
const { issuerMember } = await getNamedAccounts();

// yeeettttttt this out...
const relayHubAddress = "0x3232f21A6E08312654270c78A773f00dd61d60f5";
const { address: paymasterAddress } = await deployments.get("Paymaster");

const RelayHub = await hre.ethers.getContractFactory("RelayHub");
const relayHub = await RelayHub.attach(relayHubAddress);

// params...
const tx = await relayHub.depositFor(paymasterAddress, { value: parseEther("0.1") });
await tx.wait();

console.log('Paymaster balance:', await relayHub.balanceOf(paymasterAddress));
// console.log('Admin wallet balance', await provider.getBalance(admin.address));

});

// Reusable functions and constants.

const PAYMASTER_FACETS = [
"PaymasterTopFacet"
];

const deployPaymaster = async (
hre: HardhatRuntimeEnvironment,
issuerAddr: string
): Promise<Paymaster> => {
const { ethers, deployments, getNamedAccounts } = hre;
const { diamond } = deployments;
const { deployer } = await getNamedAccounts();

let deploy = await deployments.getOrNull("Paymaster");
if (deploy) {
console.log(`Paymaster already deployed at ${deploy.address}, skipping.`);
} else {
// Deploy the diamond with an additional initialization facet.
deploy = await diamond.deploy("Paymaster", {
from: deployer,
owner: deployer,
facets: PAYMASTER_FACETS,
execute: {
contract: "PaymasterInitFacet",
methodName: "initialize",
args: [{ issuer: issuerAddr }],
},
deterministicSalt: deploymentSalt(hre),
log: true,
});
}
// Return a handle to the diamond.
return await ethers.getContract<Paymaster>("Paymaster");
};

export { PAYMASTER_FACETS, deployPaymaster };
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2045,7 +2045,14 @@
resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.6.tgz#d11cb063a5f61a77806053e54009c40ddee49a54"
integrity sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==

"@openzeppelin/contracts@^4.9.2":
"@opengsn/contracts@^3.0.0-beta.6":
version "3.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@opengsn/contracts/-/contracts-3.0.0-beta.6.tgz#3455b7c249922a087422721689239a7d539d1138"
integrity sha512-zqd7BG339Uq5bfx40CwKXr2waaJqLN9qBVllcWhKBGnkZPKR59wVIPh2zTNzvLorndMRWB3TnOQxAr6tZKjwGQ==
dependencies:
"@openzeppelin/contracts" "^4.2.0"

"@openzeppelin/contracts@^4.2.0", "@openzeppelin/contracts@^4.9.2":
version "4.9.3"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.3.tgz#00d7a8cf35a475b160b3f0293a6403c511099364"
integrity sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==
Expand Down

0 comments on commit 1cd22ab

Please sign in to comment.