import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { BigNumber, constants } from 'ethers'; import { ethers } from 'hardhat'; import { ForwarderDeployer } from '../scripts/deployers/ForwarderDeployer'; import { VenueRegistarDeployer } from '../scripts/deployers/VenueRegistarDeployer'; import { toETH } from './utils'; import { VenueSBTDeployer } from '../scripts/deployers/VenueSBTDeployer'; import { USDCDeployer } from '../scripts/deployers/USDCDeployer'; import { UniswapV2Deployer } from '../scripts/deployers/UniswapV2Deployer'; import { ERC721E, ERC721EFactory, ReservForwarder, USDC, VenueFactory, VenueRegistar, VenueSBT } from '../types'; import { ERC721EFactoryDeployer } from '../scripts/deployers/ERC721EFactoryDeployer'; import { VenueFactoryDeployer } from '../scripts/deployers/VenueFactoryDeployer'; import { getLatestTimestamp } from '../scripts/time'; chai.use(chaiAsPromised); const { expect } = chai; let signer: SignerWithAddress; let otherSigner: SignerWithAddress; let royaltyReceiver: SignerWithAddress; let venueRegistarDeployer: VenueRegistarDeployer; let forwarderDeployer: ForwarderDeployer; let erc721EFactory: ERC721EFactory; let myVenue: VenueSBT; let venueRegistar: VenueRegistar; let forwarder: ReservForwarder; let usdc: USDC; let dai: USDC; describe('ReservForwarder', function () { before(async () => { [signer, otherSigner, royaltyReceiver] = await ethers.getSigners(); }); beforeEach(async () => { const USDC = new USDCDeployer(signer); usdc = await USDC.deploy({ name: 'USDC', symbol: 'USDC', }); dai = await USDC.deploy({ name: 'DAI', symbol: 'DAI', }); venueRegistarDeployer = new VenueRegistarDeployer(signer); venueRegistar = await venueRegistarDeployer.deployAndInitialize(toETH(1), signer.address); forwarderDeployer = new ForwarderDeployer(signer); forwarder = await forwarderDeployer.deployAndInitialize({ venueRegistar: venueRegistar.address, }); await venueRegistar.functions.setForwarder(forwarder.address); const VenueFactory = new VenueFactoryDeployer(signer); const venueFactory = (await VenueFactory.deploy(venueRegistar.address)) as VenueFactory; await venueRegistar.functions.setVenueFactory(venueFactory.address); await venueRegistar.functions.setVenueSBTVersion('1.0.0-beta.0+fob.rsv.iVenueSBT'); await venueRegistar.functions.whitelistPaymentToken(usdc.address, true); const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await expect(forwarder.functions.addfactory(erc721EFactory.address)) .to.emit(forwarder, 'NewFactory') .withArgs(1, erc721EFactory.address); await venueRegistar.connect(otherSigner).functions.deployVenue('Santiagos', 'SDV', 'sdv.com/', { value: toETH(1) }); const venues = await venueRegistar.getVenues(); myVenue = (await ethers.getContractAt('VenueSBT', venues[0], otherSigner)) as VenueSBT; }); it('Upgrades', async function () { //tries to upgrade where sender is not owner forwarderDeployer = new ForwarderDeployer(otherSigner); await expect(forwarderDeployer.upgradeToV1(forwarder)).to.be.revertedWith('Ownable: caller is not the owner'); //upgrades to V1 forwarderDeployer = new ForwarderDeployer(signer); const v1 = await forwarderDeployer.upgradeToV1(forwarder); let version = await v1.versionForwarder(); expect(version).to.be.equal('1.0.1-beta.0+fob.rsv.iForwarder'); await v1.functions.setValue(8); expect(await v1.value()).to.be.equal(8); //upgrades to v2 const v2 = await forwarderDeployer.upgradeToV2(v1); version = await v2.versionForwarder(); expect(version).to.be.equal('1.0.2-beta.0+fob.rsv.iForwarder'); await v2.functions.setValue(12); expect(await v2.value()).to.be.equal(12); expect(await v2.getValue()).to.be.equal(12); }); describe('Add Factory', () => { it('Adds Factory', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await expect(forwarder.functions.addfactory(erc721EFactory.address)) .to.emit(forwarder, 'NewFactory') .withArgs(2, erc721EFactory.address); expect(await forwarder.getFactoryAt(2)).to.be.equal(erc721EFactory.address); expect(await forwarder.getFactoryPosition(erc721EFactory.address)).to.be.equal(2); }); it('Fails if factory address is 0', async () => { await expect(forwarder.functions.addfactory(constants.AddressZero)).to.be.revertedWith( 'ForwarderFactoryAddressZero', ); }); it('Fails at trying to fetch interfaceId', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactoryNoInterface = await erc721EFactoryDeployer.deployNoInterface({ forwarder: forwarder.address, }); await expect(forwarder.functions.addfactory(erc721EFactoryNoInterface.address)).to.be.revertedWith( 'ForwarderUnableToRetrieveFactryInterface', ); }); it('Fails with wrong interface', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactoryWrongInterface = await erc721EFactoryDeployer.deployWrongInterface({ forwarder: forwarder.address, }); await expect(forwarder.functions.addfactory(erc721EFactoryWrongInterface.address)).to.be.revertedWith( 'ForwarderNotSupportedInterface', ); }); it('Fails if factory already added', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); await expect(forwarder.functions.addfactory(erc721EFactory.address)).to.be.revertedWith( 'ForwarderFactoryAlreadyAdded', ); await forwarder.functions.deprecateFactory(erc721EFactory.address, true); await expect(forwarder.functions.addfactory(erc721EFactory.address)).to.be.revertedWith( 'ForwarderFactoryAlreadyAdded', ); }); }); describe('Deprecate Factory', () => { it('Deprecates factory', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); await expect(forwarder.functions.deprecateFactory(erc721EFactory.address, true)) .to.emit(forwarder, 'DeprecateFactory') .withArgs(erc721EFactory.address, true); expect(await forwarder.deprecated(erc721EFactory.address)).to.be.true; }); it('Undo Deprecate factory', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); await forwarder.functions.deprecateFactory(erc721EFactory.address, true); expect(await forwarder.deprecated(erc721EFactory.address)).to.be.true; await expect(forwarder.functions.deprecateFactory(erc721EFactory.address, false)) .to.emit(forwarder, 'DeprecateFactory') .withArgs(erc721EFactory.address, false); expect(await forwarder.deprecated(erc721EFactory.address)).to.be.false; }); it('Fails at deprecating zero address contract', async () => { await expect(forwarder.functions.deprecateFactory(constants.AddressZero, true)).to.be.revertedWith( 'ForwarderFactoryAddressZero', ); }); it('Fails at deprecating non existent factory', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await expect(forwarder.functions.deprecateFactory(erc721EFactory.address, true)).to.be.revertedWith( 'ForwarderUnexistentFactory', ); }); it('Fails at deprecating an already deprecated factory', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); await forwarder.functions.deprecateFactory(erc721EFactory.address, true); await expect(forwarder.functions.deprecateFactory(erc721EFactory.address, true)).to.be.revertedWith( 'ForwarderDeprecatedFactory', ); }); it('Fails at undo deprecation', async () => { const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); const erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); await expect(forwarder.functions.deprecateFactory(erc721EFactory.address, false)).to.be.revertedWith( 'ForwarderNotDeprecatedFactory', ); }); }); describe('Deploy Event', async () => { it('Deploys Event', async () => { const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); await expect(myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData)) .to.emit(erc721EFactory, 'EventDeployed') .withArgs(myVenue.address, anyValue, anyValue) .to.emit(forwarder, 'Deployment') .withArgs(myVenue.address, erc721EFactory.address, anyValue) .to.emit(myVenue, 'NewEvent') .withArgs(anyValue, anyValue, anyValue); }); it('Fails with wrong payment token', async () => { const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); await expect( myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', dai.address, extraData), ).to.be.revertedWith('VenueWrongPaymentToken'); }); it('Fails with unknown venue', async () => { const venueFactory = new VenueSBTDeployer(signer); const wrongVenue = await venueFactory.deployImplicitForwarder({ baseUri: 'www.bd.com/', name: 'BadVenue', owner: otherSigner.address, royaltyFeeNumerator: BigNumber.from(1000), royaltyReceiver: otherSigner.address, symbol: 'BAD', registar: venueRegistar.address, royaltyReceiverSecondarySales: otherSigner.address, royaltyFeeNumeratorSecondarySales: BigNumber.from(1000), }); await wrongVenue.connect(otherSigner).functions.setForwarder(forwarder.address); await expect( wrongVenue.connect(otherSigner).functions.deployERC721E(1, 'BadEvent', 'BADE', '0x'), ).to.be.revertedWith('ForwarderUnknownVenue'); }); it('Fails at targeting unexistent factory', async () => { const venueFactory = new VenueSBTDeployer(signer); const wrongVenue = await venueFactory.deployImplicitForwarder({ baseUri: 'www.bd.com/', name: 'BadVenue', owner: otherSigner.address, royaltyFeeNumerator: BigNumber.from(1000), royaltyReceiver: otherSigner.address, symbol: 'BAD', registar: venueRegistar.address, royaltyReceiverSecondarySales: otherSigner.address, royaltyFeeNumeratorSecondarySales: BigNumber.from(1000), }); await wrongVenue.connect(otherSigner).functions.setForwarder(forwarder.address); await venueRegistar.functions.registerVenue(wrongVenue.address); await expect( wrongVenue.connect(otherSigner).functions.deployERC721E(2, 'BadEvent', 'BADE', '0x'), ).to.be.revertedWith('ForwarderUnexistentFactory'); }); it('Fails at targeting deprecated factory', async () => { const venueFactory = new VenueSBTDeployer(signer); const wrongVenue = await venueFactory.deployImplicitForwarder({ baseUri: 'www.bd.com/', name: 'BadVenue', owner: otherSigner.address, royaltyFeeNumerator: BigNumber.from(1000), royaltyReceiver: otherSigner.address, symbol: 'BAD', registar: venueRegistar.address, royaltyReceiverSecondarySales: otherSigner.address, royaltyFeeNumeratorSecondarySales: BigNumber.from(1000), }); await wrongVenue.connect(otherSigner).functions.setForwarder(forwarder.address); await venueRegistar.functions.registerVenue(wrongVenue.address); await forwarder.functions.deprecateFactory(erc721EFactory.address, true); await expect( wrongVenue.connect(otherSigner).functions.deployERC721E(1, 'BadEvent', 'BADE', '0x'), ).to.be.revertedWith('ForwarderDeprecatedFactory'); }); it('Fails at forwarding call', async () => { const venueFactory = new VenueSBTDeployer(signer); const wrongVenue = await venueFactory.deployImplicitForwarder({ baseUri: 'www.bd.com/', name: 'BadVenue', owner: otherSigner.address, royaltyFeeNumerator: BigNumber.from(1000), royaltyReceiver: otherSigner.address, symbol: 'BAD', registar: venueRegistar.address, royaltyReceiverSecondarySales: otherSigner.address, royaltyFeeNumeratorSecondarySales: BigNumber.from(1000), }); await wrongVenue.connect(otherSigner).functions.setForwarder(forwarder.address); await venueRegistar.functions.registerVenue(wrongVenue.address); await expect( wrongVenue.connect(otherSigner).functions.deployERC721E(1, 'BadEvent', 'BADE', '0x'), ).to.be.revertedWith('ForwarderErrorDeploying'); }); }); describe('Remove Event', () => { ``; let myEvent: ERC721E; this.beforeEach(async () => { const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); await myVenue .connect(otherSigner) .functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData); const events = await myVenue.getEvents(); myEvent = (await ethers.getContractAt('ERC721E', events[0])) as ERC721E; }); it('Removes event', async () => { await expect(myVenue.connect(otherSigner).functions.burn(0)) .to.emit(myVenue, 'BurnEvent') .withArgs(myEvent.address, anyValue) .to.emit(forwarder, 'Removed') .withArgs(myVenue.address, anyValue, myEvent.address) //is emitting wrong factoryAddress .to.emit(erc721EFactory, 'EventRemoved') .withArgs(myVenue.address, myEvent.address); //this is not being emitted }); }); });