From ee4ae7361c7611ca1b88a2578b3e0ac49bb581ce Mon Sep 17 00:00:00 2001 From: bidyut-arianelabs Date: Wed, 21 Sep 2022 15:42:50 +0530 Subject: [PATCH] unit test --- .../mock/MockMetaTransactionsHandlerFacet.sol | 20 +++++ .../protocol/facets/ConfigHandlerFacet.sol | 2 +- contracts/protocol/libs/EIP712Lib.sol | 4 +- test/protocol/MetaTransactionsHandlerTest.js | 81 ++++++++++++++++++- 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 contracts/mock/MockMetaTransactionsHandlerFacet.sol diff --git a/contracts/mock/MockMetaTransactionsHandlerFacet.sol b/contracts/mock/MockMetaTransactionsHandlerFacet.sol new file mode 100644 index 000000000..91bacdd67 --- /dev/null +++ b/contracts/mock/MockMetaTransactionsHandlerFacet.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.0; + +import { ProtocolBase } from "../protocol/bases/ProtocolBase.sol"; + +/** + * @title MockMetaTransactionsHandlerFacet + * + * @notice Handles meta-transaction requests + */ +contract MockMetaTransactionsHandlerFacet is ProtocolBase { + /** + * @notice Sets the cached chain id value. + * + * @param _chainId - chain id + */ + function setCachedChainId(uint256 _chainId) public { + protocolMetaTxInfo().cachedChainId = _chainId; + } +} diff --git a/contracts/protocol/facets/ConfigHandlerFacet.sol b/contracts/protocol/facets/ConfigHandlerFacet.sol index ef2140533..e61cfd9fd 100644 --- a/contracts/protocol/facets/ConfigHandlerFacet.sol +++ b/contracts/protocol/facets/ConfigHandlerFacet.sol @@ -66,7 +66,7 @@ contract ConfigHandlerFacet is IBosonConfigHandler, ProtocolBase { // Initialize protocol meta-transaction config params ProtocolLib.ProtocolMetaTxInfo storage pmti = protocolMetaTxInfo(); - pmti.domainSeparator = EIP712Lib.domainSeparator(PROTOCOL_NAME, PROTOCOL_VERSION); + pmti.domainSeparator = EIP712Lib.buildDomainSeparator(PROTOCOL_NAME, PROTOCOL_VERSION); pmti.cachedChainId = block.chainid; pmti.cachedThis = address(this); } diff --git a/contracts/protocol/libs/EIP712Lib.sol b/contracts/protocol/libs/EIP712Lib.sol index 4fa8b000e..4c939d65d 100644 --- a/contracts/protocol/libs/EIP712Lib.sol +++ b/contracts/protocol/libs/EIP712Lib.sol @@ -17,7 +17,7 @@ library EIP712Lib { * @param _version - The version of the protocol * @return the domain separator hash */ - function domainSeparator(string memory _name, string memory _version) internal view returns (bytes32) { + function buildDomainSeparator(string memory _name, string memory _version) internal view returns (bytes32) { return keccak256( abi.encode( @@ -85,7 +85,7 @@ library EIP712Lib { if (address(this) == cachedThis && block.chainid == cachedChainId) { return ProtocolLib.protocolMetaTxInfo().domainSeparator; } else { - return domainSeparator(PROTOCOL_NAME, PROTOCOL_VERSION); + return buildDomainSeparator(PROTOCOL_NAME, PROTOCOL_VERSION); } } diff --git a/test/protocol/MetaTransactionsHandlerTest.js b/test/protocol/MetaTransactionsHandlerTest.js index 32146988d..fb9385644 100644 --- a/test/protocol/MetaTransactionsHandlerTest.js +++ b/test/protocol/MetaTransactionsHandlerTest.js @@ -29,6 +29,8 @@ const { mockExchange, } = require("../utils/mock"); const { oneWeek, oneMonth } = require("../utils/constants"); +const { getSelectors, FacetCutAction } = require("../../scripts/util/diamond-utils.js"); + /** * Test the Boson Meta transactions Handler interface */ @@ -60,7 +62,8 @@ describe("IBosonMetaTransactionsHandler", function () { pauseHandler, bosonToken, support, - result; + result, + mockMetaTransactionsHandler; let metaTransactionsHandler, nonce, functionSignature; let seller, offerId, buyerId; let validOfferDetails, @@ -231,6 +234,43 @@ describe("IBosonMetaTransactionsHandler", function () { [bosonToken, mockToken] = await deployMockTokens(gasLimit, ["BosonToken", "Foreign20"]); }); + async function upgradeMetaTransactionsHandlerFacet() { + // Upgrade the ExchangeHandlerFacet functions + // DiamondCutFacet + const cutFacetViaDiamond = await ethers.getContractAt("DiamondCutFacet", protocolDiamond.address); + + // Deploy MockMetaTransactionsHandlerFacet + const MockMetaTransactionsHandlerFacet = await ethers.getContractFactory("MockMetaTransactionsHandlerFacet"); + const mockMetaTransactionsHandlerFacet = await MockMetaTransactionsHandlerFacet.deploy(); + await mockMetaTransactionsHandlerFacet.deployed(); + + // Define the facet cut + const facetCuts = [ + { + facetAddress: mockMetaTransactionsHandlerFacet.address, + action: FacetCutAction.Add, + functionSelectors: getSelectors(mockMetaTransactionsHandlerFacet), + }, + ]; + + // Send the DiamondCut transaction + const tx = await cutFacetViaDiamond + .connect(deployer) + .diamondCut(facetCuts, ethers.constants.AddressZero, "0x", { gasLimit }); + + // Wait for transaction to confirm + const receipt = await tx.wait(); + + // Be certain transaction was successful + assert.equal(receipt.status, 1, `Diamond upgrade failed: ${tx.hash}`); + + // Cast Diamond to MockMetaTransactionsHandlerFacet + mockMetaTransactionsHandler = await ethers.getContractAt( + "MockMetaTransactionsHandlerFacet", + protocolDiamond.address + ); + } + // Interface support (ERC-156 provided by ProtocolDiamond, others by deployed facets) context("📋 Interfaces", async function () { context("👉 supportsInterface()", async function () { @@ -422,6 +462,45 @@ describe("IBosonMetaTransactionsHandler", function () { assert.equal(result, expectedResult, "Nonce is unused"); }); + it("Should build a new domain separator if cachedChainId does not match with chain id used in signature", async function () { + await upgradeMetaTransactionsHandlerFacet(); + + // update the cached chain id + await mockMetaTransactionsHandler.setCachedChainId(123456); + + // Prepare the function signature for the facet function. + functionSignature = accountHandler.interface.encodeFunctionData("createSeller", [ + seller, + emptyAuthToken, + voucherInitValues, + ]); + + message.functionSignature = functionSignature; + + // Collect the signature components + let { r, s, v } = await prepareDataSignatureParameters( + operator, + customTransactionType, + "MetaTransaction", + message, + metaTransactionsHandler.address + ); + + // send a meta transaction, does not revert + await expect( + metaTransactionsHandler + .connect(deployer) + .executeMetaTransaction(operator.address, message.functionName, functionSignature, nonce, r, s, v) + ) + .to.emit(metaTransactionsHandler, "MetaTransactionExecuted") + .withArgs(operator.address, deployer.address, message.functionName, nonce); + + // Verify that nonce is used. Expect true. + let expectedResult = true; + result = await metaTransactionsHandler.connect(operator).isUsedNonce(nonce); + assert.equal(result, expectedResult, "Nonce is unused"); + }); + it("does not modify revert reasons", async function () { // Set seller as inactive seller.active = false;