import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; 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, toUSDC } from './utils'; import { USDCDeployer } from '../scripts/deployers/USDCDeployer'; import { ERC721EFactoryDeployer } from '../scripts/deployers/ERC721EFactoryDeployer'; import { ERC721EFactory, ReservForwarder, USDC, VenueFactory, VenueRegistar, VenueSBT } from '../types'; import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'; 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 buyer: SignerWithAddress; let secondaryBuyer: SignerWithAddress; let venueRevenueReceiver: SignerWithAddress; let venueRegistar: VenueRegistar; let usdc: USDC; let forwarder: ReservForwarder; let myVenue: VenueSBT; let erc721EFactory: ERC721EFactory; describe('VenueSBT', function () { before(async () => { [signer, otherSigner, royaltyReceiver, buyer, secondaryBuyer, venueRevenueReceiver] = await ethers.getSigners(); }); beforeEach(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'); await venueRegistar.functions.whitelistPaymentToken(usdc.address, true); const ReservForwarder = new ForwarderDeployer(signer); forwarder = await ReservForwarder.deployAndInitialize({ venueRegistar: venueRegistar.address, }); await venueRegistar.functions.setForwarder(forwarder.address); 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; expect(await myVenue.versionVenueSBT()).to.be.equal('1.0.0-beta.0+fob.rsv.iVenueSBT'); }); it('Registar Owner Sets Royalty Info', async () => { const primarySalesFee = BigNumber.from(1100); await myVenue.connect(signer).setRoyaltyInfo(royaltyReceiver.address, primarySalesFee); await expect( myVenue.connect(otherSigner).setRoyaltyInfo(royaltyReceiver.address, primarySalesFee), ).to.be.revertedWith('VenueSenderIsNotRegistarOwner'); await expect(myVenue.connect(signer).setRoyaltyInfo(constants.AddressZero, primarySalesFee)).to.be.revertedWith( 'VenueInvalidRoyaltyReceiver', ); await expect( myVenue.connect(signer).setRoyaltyInfo(royaltyReceiver.address, BigNumber.from('10001')), ).to.be.revertedWith('VenueInvalidRoyaltyFeeNumerator'); const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); // console.log(abi.encode(['uint256'], [1671591600])); const tx = await ( await myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData) ).wait(); const event = tx.events?.find((e) => e.event === 'NewEvent')?.args?._event; const ticketPrice = toUSDC(100); const saleEnd = timestamp + 60; const feePerTicket = ticketPrice.mul(primarySalesFee).div(BigNumber.from(10000)); const myEvent = await ethers.getContractAt('ERC721E', event); await myEvent.connect(otherSigner).functions.createEntry('VIP', ticketPrice, 10, 1, saleEnd); // await usdc.functions.mint(buyer.address, ticketPrice); // await usdc.connect(buyer).functions.approve(myEvent.address, ticketPrice); // await myEvent.connect(buyer).buyTickets(buyer.address, 123, 1, 1, [ticketPrice.mul(2)]); // expect(await usdc.balanceOf(myVenue.address)).to.be.equal(ticketPrice.sub(feePerTicket)); // expect(await usdc.balanceOf(royaltyReceiver.address)).to.be.equal(feePerTicket); }); it('Registar Owner Sets Secondary Sales Royalty Info', async () => { const secondarySalesFee = BigNumber.from('1100'); await myVenue.connect(signer).setRoyaltyInfoSecondarySales(royaltyReceiver.address, secondarySalesFee); await expect( myVenue.connect(otherSigner).setRoyaltyInfoSecondarySales(royaltyReceiver.address, secondarySalesFee), ).to.be.revertedWith('VenueSenderIsNotRegistarOwner'); await expect( myVenue.connect(signer).setRoyaltyInfoSecondarySales(constants.AddressZero, secondarySalesFee), ).to.be.revertedWith('VenueInvalidRoyaltyReceiver'); await expect( myVenue.connect(signer).setRoyaltyInfoSecondarySales(royaltyReceiver.address, BigNumber.from('10001')), ).to.be.revertedWith('VenueInvalidRoyaltyFeeNumerator'); const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); const tx = await ( await myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData) ).wait(); const event = tx.events?.find((e) => e.event === 'NewEvent')?.args?._event; const ticketPrice = toUSDC(100); const saleEnd = timestamp + 60; const feePerTicket = ticketPrice.mul(secondarySalesFee).div(BigNumber.from(10000)); const myEvent = await ethers.getContractAt('ERC721E', event); await myEvent.connect(otherSigner).functions.createEntry('VIP', ticketPrice, 10, 1, saleEnd); //primary sale await usdc.functions.mint(buyer.address, ticketPrice); await usdc.connect(buyer).functions.approve(myEvent.address, ticketPrice); await myEvent.connect(buyer).buyTickets(buyer.address, 123, 1, 1, [ticketPrice.mul(2)]); //secondary sale await usdc.functions.mint(secondaryBuyer.address, ticketPrice.mul(2)); await usdc.connect(secondaryBuyer).functions.approve(myEvent.address, ticketPrice.mul(2)); const tokensToBuy = [0]; const newPrices: Array = [ticketPrice.mul(3)]; await myEvent.connect(secondaryBuyer).functions.buyBatch(tokensToBuy, newPrices); expect(await usdc.balanceOf(royaltyReceiver.address)).to.be.equal(feePerTicket.mul(2)); }); it('Withdraws 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]); const tx = await ( await myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData) ).wait(); const event = tx.events?.find((e) => e.event === 'NewEvent')?.args?._event; const ticketPrice = toUSDC(100); const primarySalesFee = BigNumber.from(360); const feePerTicket = ticketPrice.mul(primarySalesFee).div(BigNumber.from(10000)); const saleEnd = timestamp + 60; const myEvent = await ethers.getContractAt('ERC721E', event); await myEvent.connect(otherSigner).functions.createEntry('VIP', ticketPrice, 10, 1, saleEnd); await usdc.functions.mint(buyer.address, ticketPrice); await usdc.connect(buyer).functions.approve(myEvent.address, ticketPrice); await myEvent.connect(buyer).buyTickets(buyer.address, 123, 1, 1, [ticketPrice.mul(2)]); expect(await usdc.balanceOf(myVenue.address)).to.be.equal(ticketPrice.sub(feePerTicket)); await myVenue.functions.withdrawToken(usdc.address); expect(await usdc.balanceOf(myVenue.address)).to.be.equal(0); expect(await usdc.balanceOf(otherSigner.address)).to.be.equal(ticketPrice.sub(feePerTicket)); await usdc.functions.mint(buyer.address, ticketPrice.mul(2)); await usdc.connect(buyer).functions.approve(myEvent.address, ticketPrice.mul(2)); const tokensToBuy = [0]; const newPrices: Array = [ticketPrice.mul(3)]; await myEvent.connect(buyer).functions.buyBatch(tokensToBuy, newPrices); }); describe('Mint', () => { it('Mints 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/', 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, 0, anyValue); const events = await myVenue.getEvents(); expect(events.length).to.be.equal(1); const myEvent = await ethers.getContractAt('ERC721E', events[0]); expect(await myEvent.name()).to.be.equal('MyEvent'); expect(await myEvent.symbol()).to.be.equal('MEV'); expect(await myEvent.owner()).to.be.equal(signer.address); }); it('Fails at Minting', async () => { let factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); const timestamp = (await getLatestTimestamp()).toNumber(); const abi = ethers.utils.defaultAbiCoder; const extraData = abi.encode(['uint256'], [timestamp + 100]); factoryType = BigNumber.from(80000); await expect( myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData), ).to.be.revertedWith('VenueFailedDeployingEvent'); }); }); describe('Burn', () => { it('Burns', 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.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData); let events = await myVenue.getEvents(); expect(events.length).to.be.equal(1); expect(await myVenue.balanceOf(myVenue.address)).to.be.equal(1); const myEvent = events[0]; expect(await myVenue.eventByToken(0)).to.be.equal(myEvent); expect(await myVenue.typeByEvent(myEvent)).to.be.equal(1); await expect(myVenue.functions.burn(0)) .to.emit(erc721EFactory, 'EventRemoved') .withArgs(myVenue.address, myEvent) .to.emit(forwarder, 'Removed') .withArgs(myVenue.address, erc721EFactory.address, myEvent) .to.emit(myVenue, 'BurnEvent') .withArgs(myEvent, 0); events = await myVenue.getEvents(); expect(events.length).to.be.equal(0); expect(await myVenue.balanceOf(myVenue.address)).to.be.equal(0); expect(await myVenue.eventByToken(0)).to.be.equal(constants.AddressZero); expect(await myVenue.typeByEvent(myEvent)).to.be.equal(0); }); it('Fails with unexistent 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 myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData); await myVenue.functions.burn(0); await expect(myVenue.functions.burn(0)).to.be.rejectedWith('VenueUnexistentToken'); }); it('Fails if event supply is gt than 0', 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]); const tx = await ( await myVenue.functions.mint(factoryType, 'MyEvent', 'MEV', 'www.sdv.mev.com/', usdc.address, extraData) ).wait(); const event = tx.events?.find((e) => e.event === 'NewEvent')?.args?._event; const saleEnd = timestamp + 60; const myEvent = await ethers.getContractAt('ERC721E', event); await myEvent.connect(otherSigner).functions.createEntry('VIP', toUSDC(10), 10, 1, saleEnd); await usdc.functions.mint(buyer.address, toUSDC(10)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(10)); await myEvent.connect(buyer).buyTickets(buyer.address, 123, 1, 1, [toUSDC(15)]); await expect(myVenue.functions.burn(0)).to.be.rejectedWith('VenueUnableToBurn'); }); }); });