Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 25, 2023
1 parent 173f7b1 commit 32ffc72
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 41 deletions.
7 changes: 3 additions & 4 deletions contracts/common/AHasForwarder.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../common/lib/LibHasForwarder.sol";

import "./lib/LibHasForwarder.sol";
import "@opengsn/contracts/src/ERC2771Recipient.sol";

/**
Expand All @@ -11,8 +10,8 @@ import "@opengsn/contracts/src/ERC2771Recipient.sol";
*/
abstract contract AHasForwarder is ERC2771Recipient {
/**
* @notice ERC2771Recipient stuff...
* FIX THE MODIFIER !!!!!!!!!!!!!!!!!!!!!!
* @notice ERC2771Recipient implementation.
* TODO: FIX MODIFIER
*/
function setTrustedForwarder(address _forwarderAddress) external {
LibHasForwarder.Data storage ds = LibHasForwarder.data();
Expand Down
5 changes: 3 additions & 2 deletions contracts/common/AHasMembers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ pragma solidity 0.8.10;
import "../lib/LibAddressSet.sol";
import "../lib/LibPaginate.sol";
import "../common/lib/LibHasMembers.sol";
import "../common/AHasForwarder.sol";
import "../interfaces/ICustomErrors.sol";

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

/// Errors.
Expand Down Expand Up @@ -94,7 +95,7 @@ abstract contract AHasMembers {
* @notice Adds a member to the list of known members.
* @param who is the address to be added.
*/
function addMember(address who) external onlyMemberManager(msg.sender) onlyValidMember(who) {
function addMember(address who) external onlyMemberManager(_msgSender()) onlyValidMember(who) {
// Add the member.
LibHasMembers.data().memberSet.add(who, false);
// Notify via callback.
Expand Down
8 changes: 4 additions & 4 deletions contracts/marketplace/MarketplaceAccessFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,25 @@ contract MarketplaceAccessFacet is AMarketplaceFacet, AHasMembers, IHasActiveMem
*/
function memberAddedToFast(address member) external {
// Verify that the given address is in fact a registered FAST contract.
if (!IssuerTopFacet(LibMarketplace.data().issuer).isFastRegistered(msg.sender)) {
if (!IssuerTopFacet(LibMarketplace.data().issuer).isFastRegistered(_msgSender())) {
revert ICustomErrors.RequiresFastContractCaller();
}
// Keep track of the member's FAST membership.
// TODO: We don't throw until we've fixed the `marketplace.fastMemberships`.
LibMarketplaceAccess.data().fastMemberships[member].add(msg.sender, true);
LibMarketplaceAccess.data().fastMemberships[member].add(_msgSender(), true);
}

/**
* @notice Callback from FAST contracts allowing the Marketplace contract to keep track of FAST memberships.
* @param member The member for which a FAST membership has been removed.
*/
function memberRemovedFromFast(address member) external {
if (!IssuerTopFacet(LibMarketplace.data().issuer).isFastRegistered(msg.sender)) {
if (!IssuerTopFacet(LibMarketplace.data().issuer).isFastRegistered(_msgSender())) {
revert ICustomErrors.RequiresFastContractCaller();
}
// Remove the tracked membership.
// TODO: We don't throw until we've fixed the `marketplace.fastMemberships`.
LibMarketplaceAccess.data().fastMemberships[member].remove(msg.sender, true);
LibMarketplaceAccess.data().fastMemberships[member].remove(_msgSender(), true);
}

/// IHasActiveMembers implementation.
Expand Down
3 changes: 1 addition & 2 deletions contracts/marketplace/MarketplaceInitFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ contract MarketplaceInitFacet is AMarketplaceFacet {

struct InitializerParams {
address issuer;
address trustedForwarder;
}

function initialize(InitializerParams calldata params) external onlyDeployer {
Expand Down Expand Up @@ -68,6 +67,6 @@ contract MarketplaceInitFacet is AMarketplaceFacet {
// ------------------------------------- //

// Initialize forwarder storage.
LibHasForwarder.data().forwarderAddress = params.trustedForwarder;
LibHasForwarder.data().forwarderAddress = address(0);
}
}
3 changes: 2 additions & 1 deletion contracts/paymaster/BasePaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ pragma solidity 0.8.10;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

import "@opengsn/contracts/src/utils/GsnTypes.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";
import "@opengsn/contracts/src/forwarder/IForwarder.sol";

/**
* @notice An abstract base class to be inherited by a concrete Paymaster.
Expand Down
4 changes: 2 additions & 2 deletions contracts/paymaster/PaymasterTopFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract PaymasterTopFacet is BasePaymaster {
(context, success, gasUseWithoutPost, relayData);
}

function versionPaymaster() external view override returns (string memory) {
return "3.0.0-beta.3+opengsn.accepteverything.ipaymaster";
function versionPaymaster() external pure override returns (string memory) {
return "3.0.0-beta.9+opengsn.tokensphere.ipaymaster";
}
}
5 changes: 1 addition & 4 deletions deploy/20_deployMarketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import { deployments } from "hardhat";
const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
console.log("----------------------------------- 20_deployMarketplace");

// TODO: From a lookup...
const trustedForwarderAddr = "0xB2b5841DBeF766d4b521221732F9B618fCf34A87";

await deployMarketplace(hre, (await deployments.get("Issuer")).address, trustedForwarderAddr);
await deployMarketplace(hre, (await deployments.get("Issuer")).address);
};
func.tags = ["DeployMarketplace"];
export default func;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"dependencies": {
"@openzeppelin/contracts": "^4.9.2",
"@opengsn/contracts": "^3.0.0-beta.6",
"@opengsn/contracts": "^3.0.0-beta.9",
"@typechain/ethers-v5": "^11.1.1",
"@typechain/hardhat": "^9.0.0",
"ethers": "^5.7.2",
Expand Down
10 changes: 3 additions & 7 deletions tasks/marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ interface MarketplaceDeployParams { }
task("marketplace-deploy", "Deploys the main Marketplace contract").setAction(
async (_params: MarketplaceDeployParams, hre) => {
const { address: issuerAddr } = await hre.deployments.get("Issuer");
// TODO: From a lookup...
const trustedForwarderAddr = "0xB2b5841DBeF766d4b521221732F9B618fCf34A87";
await deployMarketplace(hre, issuerAddr, trustedForwarderAddr);
await deployMarketplace(hre, issuerAddr);
}
);

Expand Down Expand Up @@ -64,8 +62,7 @@ const MARKETPLACE_FACETS = [

const deployMarketplace = async (
hre: HardhatRuntimeEnvironment,
issuerAddr: string,
trustedForwarderAddr: string
issuerAddr: string
): Promise<Marketplace> => {
const { ethers, deployments, getNamedAccounts } = hre;
const { diamond } = deployments;
Expand All @@ -84,8 +81,7 @@ const deployMarketplace = async (
contract: "MarketplaceInitFacet",
methodName: "initialize",
args: [{
issuer: issuerAddr,
trustedForwarder: trustedForwarderAddr
issuer: issuerAddr
}],
},
deterministicSalt: deploymentSalt(hre),
Expand Down
28 changes: 24 additions & 4 deletions test/marketplace/MarketplaceAccessFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ describe("MarketplaceAccessFacet", () => {
alice: SignerWithAddress,
bob: SignerWithAddress,
rob: SignerWithAddress,
john: SignerWithAddress;
john: SignerWithAddress,
trustedForwarder: SignerWithAddress;

let issuer: FakeContract<Issuer>,
fast: FakeContract<Fast>,
marketplace: Marketplace,
access: MarketplaceAccessFacet,
issuerMemberAccess: MarketplaceAccessFacet;
issuerMemberAccess: MarketplaceAccessFacet,
trustedForwarderAccess: MarketplaceAccessFacet;

const marketplaceDeployFixture = deployments.createFixture(
marketplaceFixtureFunc
Expand All @@ -50,7 +52,7 @@ describe("MarketplaceAccessFacet", () => {

before(async () => {
// Keep track of a few signers.
[deployer, issuerMember, alice, bob, rob, john] = await ethers.getSigners();
[deployer, issuerMember, alice, bob, rob, john, trustedForwarder] = await ethers.getSigners();
// Mock Issuer and Fast contracts.
issuer = await smock.fake("Issuer");
fast = await smock.fake("Fast");
Expand All @@ -68,11 +70,11 @@ describe("MarketplaceAccessFacet", () => {
marketplace.address
);
issuerMemberAccess = access.connect(issuerMember);
trustedForwarderAccess = access.connect(trustedForwarder);
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero,
},
});

Expand Down Expand Up @@ -147,6 +149,24 @@ describe("MarketplaceAccessFacet", () => {
await expect(subject).to.have.revertedWith(`RequiresMembersManager`);
});

it("accepts a trusted forwarder as the _msgSender()", async () => {
// Set the trusted forwarder.
await issuerMemberAccess.setTrustedForwarder(trustedForwarder.address);

// Now add member...
// Don't do this at home kids...
let encodedFunctionCall = await trustedForwarderAccess.interface.encodeFunctionData("addMember", [alice.address]);
let data = `${encodedFunctionCall}${issuerMember.address.slice(2)}`;

// Override the transaction data.
// Should now appear from the Issuer.
await trustedForwarder.sendTransaction({ data: data, to: access.address });

// Check that Alice is a member.
const subject = await marketplace.isMember(alice.address);
expect(subject).to.eq(true);
});

it("delegates to the Issuer for permission", async () => {
await issuerMemberAccess.addMember(alice.address);
expect(issuer.isMember).to.be.calledOnceWith(issuerMember.address);
Expand Down
1 change: 0 additions & 1 deletion test/marketplace/MarketplaceAutomatonsFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ describe("MarketplaceAutomatonsFacet", () => {
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ describe("MarketplaceFastDeploymentRequestsFacet", () => {
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
},
});
});
Expand Down
2 changes: 0 additions & 2 deletions test/marketplace/MarketplaceInitFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ describe("MarketplaceInitFacet", () => {
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
},
});
});
Expand All @@ -66,7 +65,6 @@ describe("MarketplaceInitFacet", () => {
);
const subject = marketplaceInitAsItself.initialize({
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
});

await expect(subject).to.have.revertedWith("AlreadyInitialized");
Expand Down
1 change: 0 additions & 1 deletion test/marketplace/MarketplaceTokenHoldersFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ describe("MarketplaceTokenHoldersFacet", () => {
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
},
});

Expand Down
1 change: 0 additions & 1 deletion test/marketplace/MarketplaceTopFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ describe("MarketplaceTopFacet", () => {
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
},
});

Expand Down
115 changes: 115 additions & 0 deletions test/paymaster/PaymasterInitFacet.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as chai from "chai";
import { expect } from "chai";
import { solidity } from "ethereum-waffle";
import { deployments, ethers } from "hardhat";
import { FakeContract, smock } from "@defi-wonderland/smock";
import { SignerWithAddress } from "hardhat-deploy-ethers/signers";
import { PaymasterTopFacet, PaymasterInitFacet } from "../../typechain";
import { paymasterFixtureFunc } from "../fixtures/paymaster";
import { BigNumber } from "ethers";
import { impersonateContract } from "../utils";
import { DEPLOYER_FACTORY_COMMON } from "../../src/utils";
import {
Issuer,
Marketplace,
Paymaster,
} from "../../typechain/hardhat-diamond-abi/HardhatDiamondABI.sol";
chai.use(solidity);
chai.use(smock.matchers);

describe("PaymasterInitFacet", () => {
let deployer: SignerWithAddress;
let issuer: FakeContract<Issuer>,
marketplace: FakeContract<Marketplace>,
paymaster: Paymaster,
top: PaymasterTopFacet;

const paymasterDeployFixture = deployments.createFixture(
paymasterFixtureFunc
);

before(async () => {
// Keep track of a few signers.
[deployer] = await ethers.getSigners();
// Mock an Issuer contract.
issuer = await smock.fake("Issuer");
marketplace = await smock.fake("Marketplace");
});

beforeEach(async () => {
await paymasterDeployFixture({
opts: {
name: "PaymasterInitFixture",
deployer: deployer.address,
afterDeploy: async (args) => {
({ paymaster } = args);
top = await ethers.getContractAt<PaymasterTopFacet>(
"PaymasterTopFacet",
paymaster.address
);
},
},
initWith: {
marketplace: marketplace.address,
},
});
});

describe("initialize", () => {
it("requires that it is not initialized", async () => {
// Attempt to re-initialize.
const paymasterInit = await ethers.getContractAt<PaymasterInitFacet>(
"PaymasterInitFacet",
paymaster.address
);
const paymasterInitAsItself = await impersonateContract(
paymasterInit,
DEPLOYER_FACTORY_COMMON.factory
);
const subject = paymasterInitAsItself.initialize({
marketplace: marketplace.address,
});

await expect(subject).to.have.revertedWith("AlreadyInitialized");
});

it("set various storage versions", async () => {
// Query the slot and parse out the STORAGE_VERSION.
const slot = ethers.utils.solidityKeccak256(
["string"],
["Paymaster.storage"]
);
const data = await ethers.provider.send("eth_getStorageAt", [
paymaster.address,
slot,
"latest",
]);
// Slice out the final 2 bytes to get the version.
const subject = ethers.utils.hexDataSlice(data, 30, 32);

// Expectations.
expect(BigNumber.from(subject).toString()).to.eq("1");
});

it("registers supported interfaces", async () => {
expect({
IERC165: await paymaster.supportsInterface("0x01ffc9a7"),
// IERC173: await paymaster.supportsInterface("0x7f5828d0"),
// IDiamondCut: await paymaster.supportsInterface("0x1f931c1c"),
// IDiamondLoupe: await paymaster.supportsInterface("0x48e2b093"),
}).to.be.eql({
IERC165: true,
// IERC173: true,
// IDiamondCut: true,
// IDiamondLoupe: true,
});
});

it("stores the given Marketplace address")
//, async () => {
// Querying the Marketplace address via the PaymasterTopFacet should return the stored address.
// const subject = await top.marketplaceAddress();
// expect(subject).to.be.eq(marketplace.address);
// });
});
});
Loading

0 comments on commit 32ffc72

Please sign in to comment.