import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { BigNumber, constants, Contract, providers, Wallet } from 'ethers'; import { ethers, waffle } from 'hardhat'; import { ForwarderDeployer } from '../scripts/deployers/ForwarderDeployer'; import { VenueRegistarDeployer } from '../scripts/deployers/VenueRegistarDeployer'; import { toETH, toUSDC } from './utils'; import { USDCDeployer } from '../scripts/deployers/USDCDeployer'; import { ERC721EFactoryDeployer } from '../scripts/deployers/ERC721EFactoryDeployer'; import { ERC721E, ERC721EFactory, ReservForwarder, PaymentSplitter, USDC, VenueFactory, VenueRegistar, VenueSBT, EventReview, } from '../types'; import { VenueFactoryDeployer } from '../scripts/deployers/VenueFactoryDeployer'; import { getLatestTimestamp } from '../scripts/time'; import { EventReviewContracts, EventReviewDeployer } from '../scripts/deployers/EventReviewDeployer'; import { GSNConfig, GSNUnresolvedConstructorInput, RelayProvider } from '@opengsn/provider'; import { HttpProvider } from 'web3-core'; import Web3 from 'web3'; chai.use(chaiAsPromised); const { expect } = chai; let signer: SignerWithAddress; let otherSigner: SignerWithAddress; let seller: SignerWithAddress; let buyer: SignerWithAddress; let venueRegistar: VenueRegistar; let usdc: USDC; let forwarder: ReservForwarder; let myVenue: VenueSBT; let erc721EFactory: ERC721EFactory; let splitter: PaymentSplitter; let eventReviewContracts: EventReviewContracts; let localProvider: providers.Web3Provider; let gsnProvider: providers.Web3Provider; let web3Provider: HttpProvider; let relayProvider: RelayProvider; let relayHub: Contract; let wallet: Wallet; //wallet with 0 eth balance let myEvent: ERC721E; let balance: BigNumber; describe('Event Review', function () { let saleEnd: number; let timestamp: number; before(async () => { [signer, otherSigner, seller, buyer] = await ethers.getSigners(); }); this.beforeAll(async () => { const USDC = new USDCDeployer(signer); usdc = await USDC.deploy({ name: 'USDC', symbol: 'USDC', }); const venueRegistarDeployer = new VenueRegistarDeployer(signer); venueRegistar = await venueRegistarDeployer.deployAndInitialize(toETH(1), signer.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'); const eventReviewDeployer = new EventReviewDeployer(signer); eventReviewContracts = await eventReviewDeployer.deploy({ venueRegistar: venueRegistar.address }); await venueRegistar.functions.setTokenReviewParams( eventReviewContracts.eventReview.address, eventReviewContracts.eventReviewPaymaster.address, toETH(0.1), ); const ReservForwarder = new ForwarderDeployer(signer); forwarder = await ReservForwarder.deployAndInitialize({ venueRegistar: venueRegistar.address, }); await venueRegistar.functions.setForwarder(forwarder.address); await venueRegistar.functions.whitelistPaymentToken(usdc.address, true); const erc721EFactoryDeployer = new ERC721EFactoryDeployer(signer); erc721EFactory = await erc721EFactoryDeployer.deploy({ forwarder: forwarder.address, }); await forwarder.functions.addfactory(erc721EFactory.address); expect(await forwarder.getFactoryAt(1)).to.be.equal(erc721EFactory.address); await venueRegistar.functions.ownerDeployVenue('Santiagos', 'SDV', 'sdv.com/', otherSigner.address); const venues = await venueRegistar.getVenues(); myVenue = (await ethers.getContractAt('VenueSBT', venues[0], otherSigner)) as VenueSBT; const splitterAdd = await venueRegistar.splitterByVenue(myVenue.address); splitter = (await ethers.getContractAt('PaymentSplitter', splitterAdd)) as PaymentSplitter; //GSN localProvider = waffle.provider; web3Provider = new Web3.providers.HttpProvider('http://localhost:8545/'); relayHub = await ethers.getContractAt('IRelayHub', eventReviewContracts.gsnRelayHub); const gsnConfig: Partial = { loggerConfiguration: { logLevel: 'error', }, performDryRunViewRelayCall: false, paymasterAddress: eventReviewContracts.eventReviewPaymaster.address, }; const input: GSNUnresolvedConstructorInput = { provider: web3Provider as any, config: gsnConfig, }; wallet = ethers.Wallet.createRandom(); relayProvider = await RelayProvider.newProvider(input).init(); relayProvider.addAccount(wallet.privateKey as string); const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); let tx = await ( await myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData, { value: toETH(5), }) ).wait(); const event = tx.events?.find((e) => e.event === 'NewEvent')?.args?._event; myEvent = (await ethers.getContractAt('ERC721E', event)) as ERC721E; saleEnd = timestamp + 60; tx = await (await myEvent.connect(otherSigner).functions.createEntry('VIP', toUSDC(100), 10, 10, saleEnd)).wait(); let entryPos = tx.events?.find((e) => e.event === 'NewEntry')?.args?.pos as BigNumber; await usdc.functions.mint(seller.address, toUSDC(1000)); await usdc.connect(seller).functions.approve(myEvent.address, toUSDC(1000)); const prices = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(wallet.address, 123, entryPos, 10, prices); }); describe('Perform Review', () => { it('Funds paymaster when creating an event', async () => { const paymasterBalance = await myVenue.getPaymasterBalance(eventReviewContracts.eventReviewPaymaster.address); expect(paymasterBalance).to.be.equal(toETH(5)); }); it('Does review', async () => { const eventReview = (await ethers.getContractAt( 'EventReview', eventReviewContracts.eventReview.address, wallet, )) as EventReview; const gsnProvider = new providers.Web3Provider(relayProvider as unknown as providers.ExternalProvider); await ( await eventReview .connect(gsnProvider.getSigner(wallet.address)) .doReview(myVenue.address, myEvent.address, 0, 50, { gasLimit: '400000' }) ).wait(); expect(await eventReview.balanceOf(myVenue.address)).to.be.equal(1); const review = await eventReview.getReview(0); expect(review.reviewer).to.be.equal(wallet.address); expect(review.venue).to.be.equal(myVenue.address); expect(review._event).to.be.equal(myEvent.address); expect(review.eventTokenId).to.be.equal(0); expect(review.stars).to.be.equal(50); expect(await eventReview.ownerOf(0)).to.be.equal(myVenue.address); balance = await myVenue.getPaymasterBalance(eventReviewContracts.eventReviewPaymaster.address); expect(balance).to.be.lt(toETH(5)); }); it('Does review of another ticket', async () => { const eventReview = (await ethers.getContractAt( 'EventReview', eventReviewContracts.eventReview.address, wallet, )) as EventReview; const gsnProvider = new providers.Web3Provider(relayProvider as unknown as providers.ExternalProvider); await ( await eventReview .connect(gsnProvider.getSigner(wallet.address)) .doReview(myVenue.address, myEvent.address, 1, 45, { gasLimit: '400000' }) ).wait(); expect(await eventReview.balanceOf(myVenue.address)).to.be.equal(2); const review = await eventReview.getReview(1); expect(review.reviewer).to.be.equal(wallet.address); expect(review.venue).to.be.equal(myVenue.address); expect(review._event).to.be.equal(myEvent.address); expect(review.eventTokenId).to.be.equal(1); expect(review.stars).to.be.equal(45); expect(await eventReview.ownerOf(0)).to.be.equal(myVenue.address); const newBalance = await myVenue.getPaymasterBalance(eventReviewContracts.eventReviewPaymaster.address); expect(newBalance).to.be.lt(balance); }); }); });