|
| 1 | +import { expect } from "chai"; |
| 2 | +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; |
| 3 | +import helpers = require("@nomicfoundation/hardhat-network-helpers"); |
| 4 | +import { ethers } from "hardhat"; |
| 5 | +import { constants } from "ethers"; |
| 6 | +import { PMPFixtureConfig, setupPMPFixture } from "../../pmpFixtures"; |
| 7 | +import { Contract } from "ethers"; |
| 8 | +import { Logger } from "@ethersproject/logger"; |
| 9 | +// hide nuisance logs about event overloading |
| 10 | +Logger.setLogLevel(Logger.levels.ERROR); |
| 11 | + |
| 12 | +interface T_ConfigWithHook extends PMPFixtureConfig { |
| 13 | + hook: Contract; |
| 14 | +} |
| 15 | + |
| 16 | +describe("InjectBlockTimestamp", function () { |
| 17 | + async function _beforeEach(): Promise<T_ConfigWithHook> { |
| 18 | + const config = await loadFixture(setupPMPFixture); |
| 19 | + // deploy the hook |
| 20 | + const hookFactory = await ethers.getContractFactory("InjectBlockTimestamp"); |
| 21 | + const hook = await hookFactory.deploy(); |
| 22 | + await hook.deployed(); |
| 23 | + // configure the hook on project zero |
| 24 | + await config.pmp.connect(config.accounts.artist).configureProjectHooks( |
| 25 | + config.genArt721Core.address, |
| 26 | + config.projectZero, |
| 27 | + constants.AddressZero, // tokenPMPPostConfigHook |
| 28 | + hook.address // tokenPMPReadAugmentationHook |
| 29 | + ); |
| 30 | + return { |
| 31 | + ...config, |
| 32 | + hook, |
| 33 | + } as T_ConfigWithHook; |
| 34 | + } |
| 35 | + |
| 36 | + describe("onTokenPMPReadAugmentation", function () { |
| 37 | + it("appends blockTimestamp to empty params", async function () { |
| 38 | + const config = await loadFixture(_beforeEach); |
| 39 | + |
| 40 | + const augmentedParams = await config.hook.onTokenPMPReadAugmentation( |
| 41 | + config.genArt721Core.address, |
| 42 | + config.projectZeroTokenZero, |
| 43 | + [] |
| 44 | + ); |
| 45 | + |
| 46 | + expect(augmentedParams.length).to.equal(1); |
| 47 | + expect(augmentedParams[0].key).to.equal("blockTimestamp"); |
| 48 | + // value should be a numeric string representing a reasonable timestamp |
| 49 | + const timestamp = parseInt(augmentedParams[0].value, 10); |
| 50 | + expect(timestamp).to.be.greaterThan(0); |
| 51 | + }); |
| 52 | + |
| 53 | + it("appends blockTimestamp to existing params", async function () { |
| 54 | + const config = await loadFixture(_beforeEach); |
| 55 | + |
| 56 | + const augmentedParams = await config.hook.onTokenPMPReadAugmentation( |
| 57 | + config.genArt721Core.address, |
| 58 | + config.projectZeroTokenZero, |
| 59 | + [ |
| 60 | + { key: "param1", value: "value1" }, |
| 61 | + { key: "param2", value: "value2" }, |
| 62 | + ] |
| 63 | + ); |
| 64 | + |
| 65 | + expect(augmentedParams.length).to.equal(3); |
| 66 | + expect(augmentedParams[0].key).to.equal("param1"); |
| 67 | + expect(augmentedParams[0].value).to.equal("value1"); |
| 68 | + expect(augmentedParams[1].key).to.equal("param2"); |
| 69 | + expect(augmentedParams[1].value).to.equal("value2"); |
| 70 | + expect(augmentedParams[2].key).to.equal("blockTimestamp"); |
| 71 | + const timestamp = parseInt(augmentedParams[2].value, 10); |
| 72 | + expect(timestamp).to.be.greaterThan(0); |
| 73 | + }); |
| 74 | + |
| 75 | + it("returns different timestamps after time passes", async function () { |
| 76 | + const config = await loadFixture(_beforeEach); |
| 77 | + |
| 78 | + const params1 = await config.hook.onTokenPMPReadAugmentation( |
| 79 | + config.genArt721Core.address, |
| 80 | + config.projectZeroTokenZero, |
| 81 | + [] |
| 82 | + ); |
| 83 | + const timestamp1 = parseInt(params1[0].value, 10); |
| 84 | + |
| 85 | + // advance time by 60 seconds |
| 86 | + await helpers.time.increase(60); |
| 87 | + |
| 88 | + const params2 = await config.hook.onTokenPMPReadAugmentation( |
| 89 | + config.genArt721Core.address, |
| 90 | + config.projectZeroTokenZero, |
| 91 | + [] |
| 92 | + ); |
| 93 | + const timestamp2 = parseInt(params2[0].value, 10); |
| 94 | + |
| 95 | + expect(timestamp2).to.be.greaterThan(timestamp1); |
| 96 | + expect(timestamp2 - timestamp1).to.be.at.least(60); |
| 97 | + }); |
| 98 | + }); |
| 99 | + |
| 100 | + describe("Integration with PMP system", function () { |
| 101 | + it("returns blockTimestamp via PMP getTokenParams", async function () { |
| 102 | + const config = await loadFixture(_beforeEach); |
| 103 | + |
| 104 | + const params = await config.pmp.getTokenParams( |
| 105 | + config.genArt721Core.address, |
| 106 | + config.projectZeroTokenZero |
| 107 | + ); |
| 108 | + |
| 109 | + // should have at least the blockTimestamp param |
| 110 | + const timestampParam = params.find( |
| 111 | + (p: { key: string }) => p.key === "blockTimestamp" |
| 112 | + ); |
| 113 | + expect(timestampParam).to.not.be.undefined; |
| 114 | + const timestamp = parseInt(timestampParam!.value, 10); |
| 115 | + expect(timestamp).to.be.greaterThan(0); |
| 116 | + }); |
| 117 | + }); |
| 118 | + |
| 119 | + describe("supportsInterface", function () { |
| 120 | + it("supports IPMPAugmentHook interface", async function () { |
| 121 | + const config = await loadFixture(_beforeEach); |
| 122 | + // IPMPAugmentHook interface ID |
| 123 | + const IPMPAugmentHookInterfaceId = "0x58f8699f"; |
| 124 | + expect(await config.hook.supportsInterface(IPMPAugmentHookInterfaceId)).to |
| 125 | + .be.true; |
| 126 | + }); |
| 127 | + |
| 128 | + it("supports ERC165 interface", async function () { |
| 129 | + const config = await loadFixture(_beforeEach); |
| 130 | + const IERC165InterfaceId = "0x01ffc9a7"; |
| 131 | + expect(await config.hook.supportsInterface(IERC165InterfaceId)).to.be |
| 132 | + .true; |
| 133 | + }); |
| 134 | + |
| 135 | + it("does not support random interface", async function () { |
| 136 | + const config = await loadFixture(_beforeEach); |
| 137 | + expect(await config.hook.supportsInterface("0xdeadbeef")).to.be.false; |
| 138 | + }); |
| 139 | + }); |
| 140 | +}); |
0 commit comments