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 { UniswapV2Deployer } from '../scripts/deployers/UniswapV2Deployer'; import { ERC721EFactoryDeployer } from '../scripts/deployers/ERC721EFactoryDeployer'; import { ERC721E, ERC721EFactory, ReservForwarder, USDC, VenueFactory, VenueRegistar, VenueSBT } from '../types'; import { getLatestTimestamp, timeIncreaseTo } from '../scripts/time'; import { VenueFactoryDeployer } from '../scripts/deployers/VenueFactoryDeployer'; chai.use(chaiAsPromised); const { expect } = chai; let signer: SignerWithAddress; let otherSigner: SignerWithAddress; let seller: SignerWithAddress; let buyer: SignerWithAddress; let otherBuyer: SignerWithAddress; let otherBuyer2: SignerWithAddress; let splitter: string; let venueRegistar: VenueRegistar; let usdc: USDC; let forwarder: ReservForwarder; let myVenue: VenueSBT; let erc721EFactory: ERC721EFactory; let myEvent: ERC721E; describe('ERC721A Marketplace', function () { let saleEnd: number; let timestamp: number; before(async () => { [signer, otherSigner, seller, buyer, otherBuyer, otherBuyer2] = 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.whitelistPaymentToken(usdc.address, true); await venueRegistar.functions.setVenueSBTVersion('1.0.0-beta.0+fob.rsv.iVenueSBT'); 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; splitter = await venueRegistar.splitterByVenue(myVenue.address); const factoryType = await forwarder.getFactoryPosition(erc721EFactory.address); 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; myEvent = (await ethers.getContractAt('ERC721E', event)) as ERC721E; saleEnd = timestamp + 60; }); describe('Buy Batch', () => { it('Buys batch', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1500)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1500)); const tokensToBuy = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; const newPrices: Array = new Array(10).fill(toUSDC(200)); const buyerBeforeBalance = await usdc.balanceOf(buyer.address); const sellerBeforeBalance = await usdc.balanceOf(seller.address); await expect(myEvent.connect(buyer).functions.buyBatch(tokensToBuy, newPrices)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 0, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 1, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 2, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 3, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 4, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 5, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 6, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 7, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 8, toUSDC(150)) .to.emit(myEvent, 'Sell') .withArgs(buyer.address, seller.address, 9, toUSDC(150)); expect(await myEvent.balanceOf(buyer.address)).to.be.equal(10); expect(await myEvent.ownerOf(9)).to.be.equal(buyer.address); expect(await myEvent.priceByToken(9)).to.be.equal(toUSDC(200)); const totalPaid = toUSDC(150).mul(10); expect(await usdc.balanceOf(buyer.address)).to.be.equal(buyerBeforeBalance.sub(totalPaid)); expect(await usdc.balanceOf(seller.address)).to.be.equal( sellerBeforeBalance.add(totalPaid.sub(totalPaid.mul(10).div(100))), ); //minus 10% expect(await usdc.balanceOf(splitter)).to.be.equal(totalPaid.sub(totalPaid.mul(90).div(100))); //minus 90% }); it('Fails with invalid length batch', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1500)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1500)); const tokensToBuy = [0, 1, 2, 3, 4, 5, 6, 7, 8]; const newPrices: Array = new Array(10).fill(toUSDC(200)); await expect(myEvent.connect(buyer).functions.buyBatch(tokensToBuy, newPrices)).to.be.revertedWith( 'ERC721AMKInvalidBatchLengths', ); }); it('Fails with invalid price', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1500)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1500)); const tokensToBuy = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let newPrices: Array = new Array(10).fill(toUSDC(200)); newPrices[3] = BigNumber.from(0); await expect(myEvent.connect(buyer).functions.buyBatch(tokensToBuy, newPrices)).to.be.revertedWith( 'ERC721AMKInvalidSellPrice', ); }); }); describe('Set Offer', () => { it('Sets offer', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); let tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let offerPrices: Array = new Array(10).fill(toUSDC(200)); await expect(myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60)) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 0, 1) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 1, 2) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 2, 3) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 3, 4) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 4, 5) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 5, 6) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 6, 7) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 7, 8) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 8, 9) .to.emit(myEvent, 'NewOffer') .withArgs(buyer.address, 9, 10); const offer = await myEvent.getOffer(3); expect(offer.tokenId).to.be.equal(2); expect(offer.offerPrice).to.be.equal(toUSDC(200)); expect(offer.buyer).to.be.equal(buyer.address); expect(offer.offerDeadline).to.be.equal(timestamp + 60); const offersByBuyer = await myEvent.getOffersByBuyer(buyer.address, true, false); expect(offersByBuyer.length).to.be.equal(10); expect(offersByBuyer.map((o) => o.toNumber())).to.have.members([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); tokensToOffer = [0, 1, 2, 3, 4]; offerPrices = new Array(5).fill(toUSDC(250)); await myEvent.connect(otherBuyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60); const offersByToken = await myEvent.getOffersByToken(0, true, false); expect(offersByToken.length).to.be.equal(2); expect(offersByToken.map((o) => o.toNumber())).to.have.members([1, 11]); }); it('Fails with wrong batch length', async () => { const timestamp = (await getLatestTimestamp()).toNumber(); const saleEnd = timestamp + 60; const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8]; const offerPrices: Array = new Array(10).fill(toUSDC(200)); await expect( myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60), ).to.be.revertedWith('ERC721AMKInvalidBatchLengths'); }); it('Fails with wrong deadline', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; const offerPrices: Array = new Array(10).fill(toUSDC(200)); await expect( myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp - 1), ).to.be.revertedWith('ERC721AMKWrongDeadline'); }); it('Fails with unexistent token', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10]; const offerPrices: Array = new Array(10).fill(toUSDC(200)); const timestamp = (await getLatestTimestamp()).toNumber(); await expect( myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60), ).to.be.revertedWith('ERC721AMKUnexistentToken'); }); it('Fails with wrong offer price', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let offerPrices: Array = new Array(10).fill(toUSDC(200)); offerPrices[6] = BigNumber.from(0); const timestamp = (await getLatestTimestamp()).toNumber(); await expect( myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60), ).to.be.revertedWith('ERC721AMKInvalidOfferPrice'); }); }); describe('Offers by token', () => { it('Gets active and inactive offers', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const timestamp = (await getLatestTimestamp()).toNumber(); let tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let offerPrices: Array = new Array(10).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); tokensToOffer = [0, 1, 2, 3, 4]; offerPrices = new Array(5).fill(toUSDC(250)); await myEvent.connect(otherBuyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60); tokensToOffer = [0, 1, 2]; offerPrices = new Array(3).fill(toUSDC(300)); await myEvent.connect(otherBuyer2).functions.setOffers(tokensToOffer, offerPrices, timestamp + 30); let active = true; let inactive = false; let offers = await myEvent.getOffersByToken(1, active, inactive); expect(offers.length).to.be.equal(3); expect(offers.map((o) => o.toNumber())).to.have.members([2, 12, 17]); await timeIncreaseTo(timestamp + 40); offers = await myEvent.getOffersByToken(1, active, inactive); expect(offers.length).to.be.equal(3); expect(offers.map((o) => o.toNumber())).to.have.members([2, 12, 0]); inactive = true; offers = await myEvent.getOffersByToken(1, active, inactive); expect(offers.length).to.be.equal(3); expect(offers.map((o) => o.toNumber())).to.have.members([2, 12, 17]); active = false; offers = await myEvent.getOffersByToken(1, active, inactive); expect(offers.length).to.be.equal(3); expect(offers.map((o) => o.toNumber())).to.have.members([0, 0, 17]); }); }); describe('Offers by buyer', () => { it('Gets active and inactive offers', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const timestamp = (await getLatestTimestamp()).toNumber(); let tokensToOffer = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let offerPrices: Array = new Array(10).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); tokensToOffer = [0, 1, 2, 3, 4]; offerPrices = new Array(5).fill(toUSDC(250)); await myEvent.connect(otherBuyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60); tokensToOffer = [0, 1, 2]; offerPrices = new Array(3).fill(toUSDC(300)); await myEvent.connect(otherBuyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 30); let active = true; let inactive = false; let offers = await myEvent.getOffersByBuyer(otherBuyer.address, active, inactive); expect(offers.length).to.be.equal(8); expect(offers.map((o) => o.toNumber())).to.have.members([11, 12, 13, 14, 15, 16, 17, 18]); await timeIncreaseTo(timestamp + 40); offers = await myEvent.getOffersByBuyer(otherBuyer.address, active, inactive); expect(offers.length).to.be.equal(8); expect(offers.map((o) => o.toNumber())).to.have.members([11, 12, 13, 14, 15, 0, 0, 0]); inactive = true; offers = await myEvent.getOffersByBuyer(otherBuyer.address, active, inactive); expect(offers.length).to.be.equal(8); expect(offers.map((o) => o.toNumber())).to.have.members([11, 12, 13, 14, 15, 16, 17, 18]); active = false; offers = await myEvent.getOffersByBuyer(otherBuyer.address, active, inactive); expect(offers.length).to.be.equal(8); expect(offers.map((o) => o.toNumber())).to.have.members([0, 0, 0, 0, 0, 16, 17, 18]); }); }); describe('Cancel offer', () => { it('Cancels offer', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); await expect(myEvent.connect(buyer).functions.cancelOffers([1, 2, 3])) .to.emit(myEvent, 'CancelOffer') .withArgs(1) .to.emit(myEvent, 'CancelOffer') .withArgs(2) .to.emit(myEvent, 'CancelOffer') .withArgs(3); const offer = await myEvent.getOffer(3); expect(offer.tokenId).to.be.equal(0); expect(offer.buyer).to.be.equal(constants.AddressZero); expect(offer.offerDeadline).to.be.equal(0); expect(offer.offerPrice).to.be.equal(0); let active = true; let inactive = false; let offers = await myEvent.getOffersByBuyer(buyer.address, active, inactive); expect(offers.length).to.be.equal(6); expect(offers.map((o) => o.toNumber())).to.have.members([0, 0, 0, 4, 5, 6]); active = false; inactive = true; offers = await myEvent.getOffersByBuyer(buyer.address, active, inactive); expect(offers.length).to.be.equal(6); expect(offers.map((o) => o.toNumber())).to.have.members([1, 2, 3, 0, 0, 0]); }); it('Fails if sender is not offer owner', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); await expect(myEvent.connect(otherBuyer).functions.cancelOffers([1, 2, 3])).to.be.revertedWith( 'ERC721AMKNotOfferOwner', ); }); }); describe('Accept Offer', () => { it('Accepts offer', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1200)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1200)); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); const buyerBeforeBalance = await usdc.balanceOf(buyer.address); const sellerBeforeBalance = await usdc.balanceOf(seller.address); await expect(myEvent.connect(seller).functions.acceptOffers([1, 2, 3, 4, 5, 6])) .to.emit(myEvent, 'AcceptOffer') .withArgs(1) .to.emit(myEvent, 'AcceptOffer') .withArgs(2) .to.emit(myEvent, 'AcceptOffer') .withArgs(3) .to.emit(myEvent, 'AcceptOffer') .withArgs(4) .to.emit(myEvent, 'AcceptOffer') .withArgs(5) .to.emit(myEvent, 'AcceptOffer') .withArgs(6); const totalPaid = toUSDC(200).mul(6); expect(await usdc.balanceOf(buyer.address)).to.be.equal(buyerBeforeBalance.sub(totalPaid)); expect(await usdc.balanceOf(seller.address)).to.be.equal( sellerBeforeBalance.add(totalPaid.sub(totalPaid.mul(10).div(100))), ); //minus 10% expect(await usdc.balanceOf(splitter)).to.be.equal(totalPaid.sub(totalPaid.mul(90).div(100))); //minus 90% expect(await myEvent.ownerOf(0)).to.be.equal(buyer.address); expect(await myEvent.ownerOf(1)).to.be.equal(buyer.address); expect(await myEvent.ownerOf(2)).to.be.equal(buyer.address); expect(await myEvent.ownerOf(3)).to.be.equal(buyer.address); expect(await myEvent.ownerOf(4)).to.be.equal(buyer.address); expect(await myEvent.ownerOf(5)).to.be.equal(buyer.address); }); it('Fails on unexistent offer', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1200)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1200)); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); await myEvent.connect(buyer).functions.cancelOffers([6]); await expect(myEvent.connect(seller).functions.acceptOffers([1, 2, 3, 4, 5, 6])).to.be.revertedWith( 'ERC721AMKUnexistentOffer', ); }); it('Fails if seller is not token owner', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1200)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1200)); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); await myEvent.connect(seller).functions.transferFrom(seller.address, otherBuyer.address, 0); await expect(myEvent.connect(seller).functions.acceptOffers([1, 2, 3, 4, 5, 6])).to.be.revertedWith( 'ERC721AMKNotTokenOwner', ); }); it('Fails if offer deadline is over', async () => { const 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: Array = new Array(10).fill(toUSDC(150)); await myEvent.connect(seller).buyTickets(seller.address, 123, entryPos, 10, prices); await usdc.functions.mint(buyer.address, toUSDC(1200)); await usdc.connect(buyer).functions.approve(myEvent.address, toUSDC(1200)); const timestamp = (await getLatestTimestamp()).toNumber(); const tokensToOffer = [0, 1, 2, 3, 4, 5]; const offerPrices: Array = new Array(6).fill(toUSDC(200)); await myEvent.connect(buyer).functions.setOffers(tokensToOffer, offerPrices, timestamp + 60 * 5); await timeIncreaseTo(timestamp + 60 * 5 + 10); await expect(myEvent.connect(seller).functions.acceptOffers([1, 2, 3, 4, 5, 6])).to.be.revertedWith( 'ERC721AMKOfferDeadlineOver', ); }); }); });