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 5f6dcc8
Show file tree
Hide file tree
Showing 16 changed files with 116 additions and 49 deletions.
62 changes: 57 additions & 5 deletions contracts/common/AHasForwarder.sol
Original file line number Diff line number Diff line change
@@ -1,22 +1,74 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

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

import "@opengsn/contracts/src/ERC2771Recipient.sol";
import "hardhat/console.sol";

/**
* @title The Forwarder Smart Contract.
* @notice The HasForwarder abstract contract is in charge of...
*/
abstract contract AHasForwarder is ERC2771Recipient {
abstract contract AHasForwarder is IERC2771Recipient {
/**
* @notice ERC2771Recipient stuff...
* FIX THE MODIFIER !!!!!!!!!!!!!!!!!!!!!!
* @notice ERC2771Recipient implementation.
* TODO: FIX MODIFIER
*/
function setTrustedForwarder(address _forwarderAddress) external {
LibHasForwarder.Data storage ds = LibHasForwarder.data();
ds.forwarderAddress = _forwarderAddress;
_setTrustedForwarder(_forwarderAddress);
}

/*
* Forwarder singleton we accept calls from
*/
address private _trustedForwarder;

/**
* :warning: **Warning** :warning: The Forwarder can have a full control over your Recipient. Only trust verified Forwarder.
* @notice Method is not a required method to allow Recipients to trust multiple Forwarders. Not recommended yet.
* @return forwarder The address of the Forwarder contract that is being used.
*/
function getTrustedForwarder() public view virtual returns (address forwarder) {
return _trustedForwarder;
}

function _setTrustedForwarder(address _forwarder) internal {
_trustedForwarder = _forwarder;
}

/// @inheritdoc IERC2771Recipient
function isTrustedForwarder(address forwarder) public view virtual override returns (bool) {
return forwarder == _trustedForwarder;
}

/// @inheritdoc IERC2771Recipient
function _msgSender() internal view virtual override returns (address ret) {
console.log("msg.sender %s", msg.sender);
console.log("original msg.data");
console.logBytes(msg.data);
if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) {
// At this point we know that the sender is a trusted forwarder,
// so we trust that the last bytes of msg.data are the verified sender address.
// extract sender address from the end of msg.data
assembly {
ret := shr(96, calldataload(sub(calldatasize(), 20)))
}
console.log("last 20 bytes from msg.data %s", ret);
} else {
ret = msg.sender;
}
}

/// @inheritdoc IERC2771Recipient
function _msgData() internal view virtual override returns (bytes calldata ret) {
if (msg.data.length >= 20 && isTrustedForwarder(msg.sender)) {
return msg.data[0:msg.data.length - 20];

Check warning on line 69 in contracts/common/AHasForwarder.sol

View check run for this annotation

Codecov / codecov/patch

contracts/common/AHasForwarder.sol#L67-L69

Added lines #L67 - L69 were not covered by tests
} else {
return msg.data;

Check warning on line 71 in contracts/common/AHasForwarder.sol

View check run for this annotation

Codecov / codecov/patch

contracts/common/AHasForwarder.sol#L71

Added line #L71 was not covered by tests
}
}
}
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())) {

Check warning on line 59 in contracts/marketplace/MarketplaceAccessFacet.sol

View check run for this annotation

Codecov / codecov/patch

contracts/marketplace/MarketplaceAccessFacet.sol#L59

Added line #L59 was not covered by tests
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);

Check warning on line 64 in contracts/marketplace/MarketplaceAccessFacet.sol

View check run for this annotation

Codecov / codecov/patch

contracts/marketplace/MarketplaceAccessFacet.sol#L64

Added line #L64 was not covered by tests
}

/**
* @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())) {

Check warning on line 72 in contracts/marketplace/MarketplaceAccessFacet.sol

View check run for this annotation

Codecov / codecov/patch

contracts/marketplace/MarketplaceAccessFacet.sol#L72

Added line #L72 was not covered by tests
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);

Check warning on line 77 in contracts/marketplace/MarketplaceAccessFacet.sol

View check run for this annotation

Codecov / codecov/patch

contracts/marketplace/MarketplaceAccessFacet.sol#L77

Added line #L77 was not covered by tests
}

/// 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";

Check warning on line 35 in contracts/paymaster/PaymasterTopFacet.sol

View check run for this annotation

Codecov / codecov/patch

contracts/paymaster/PaymasterTopFacet.sol#L34-L35

Added lines #L34 - L35 were not covered by tests
}
}
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
34 changes: 29 additions & 5 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,
issuer: issuer.address
},
});

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

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

console.log('forwarder', await issuerMemberAccess.getTrustedForwarder());
console.log('issuer', issuerMember.address);
console.log('alice', alice.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.
// Issuer really called this :D
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
3 changes: 1 addition & 2 deletions test/marketplace/MarketplaceAutomatonsFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ describe("MarketplaceAutomatonsFacet", () => {
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ describe("MarketplaceFastDeploymentRequestsFacet", () => {
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
},
});
});
Expand Down
6 changes: 2 additions & 4 deletions test/marketplace/MarketplaceInitFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ describe("MarketplaceInitFacet", () => {
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
},
});
});
Expand All @@ -65,8 +64,7 @@ describe("MarketplaceInitFacet", () => {
DEPLOYER_FACTORY_COMMON.factory
);
const subject = marketplaceInitAsItself.initialize({
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
});

await expect(subject).to.have.revertedWith("AlreadyInitialized");
Expand Down
3 changes: 1 addition & 2 deletions test/marketplace/MarketplaceTokenHoldersFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ describe("MarketplaceTokenHoldersFacet", () => {
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
},
});

Expand Down
3 changes: 1 addition & 2 deletions test/marketplace/MarketplaceTopFacet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ describe("MarketplaceTopFacet", () => {
},
},
initWith: {
issuer: issuer.address,
trustedForwarder: ethers.constants.AddressZero
issuer: issuer.address
},
});

Expand Down
11 changes: 7 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2045,12 +2045,15 @@
resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.6.tgz#d11cb063a5f61a77806053e54009c40ddee49a54"
integrity sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==

"@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==
"@opengsn/contracts@^3.0.0-beta.9":
version "3.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@opengsn/contracts/-/contracts-3.0.0-beta.10.tgz#eaab77c696cd0ea5074b6875d71166439e37a28f"
integrity sha512-phnrtNmLO1dre2MniOcbNelNN5GnBMNsIDeFRHKrkFpcgwzf8PTCqfDCVT7pKGoQOwP526m6gDTV1Fj2Wz5SYw==
dependencies:
"@ethersproject/abi" "^5.7.0"
"@ethersproject/providers" "^5.7.2"
"@openzeppelin/contracts" "^4.2.0"
ethers "^5.7.2"

"@openzeppelin/contracts@^4.2.0", "@openzeppelin/contracts@^4.9.2":
version "4.9.3"
Expand Down

0 comments on commit 5f6dcc8

Please sign in to comment.