ethers/lib/utils#parseEther TypeScript Examples

The following examples show how to use ethers/lib/utils#parseEther. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From hubble-contracts with MIT License 6 votes vote down vote up
export function toWei(ether: string): Wei {
    return parseEther(ether).toString();
}
Example #2
Source File: uniswapV3Fixture.ts    From index-coop-smart-contracts with Apache License 2.0 5 votes vote down vote up
_getSqrtPriceX96(_ratio: number): BigNumber {
    return parseEther(Math.sqrt(_ratio).toFixed(18).toString()).mul(BigNumber.from(2).pow(96)).div(ether(1));
  }
Example #3
Source File: swapKiwi.test.ts    From swap.kiwi with GNU General Public License v3.0 5 votes vote down vote up
describe("SwapKiwi", async function () {
  let SwapKiwi: Deployment;
  let swapKiwi: SwapKiwi;
  let TestERC721: Deployment;
  let appUserERC721: TestERC721;
  let otherAppUserERC721: TestERC721;
  let TestERC1155: Deployment;
  let appUserERC1155: TestERC1155;
  let otherAppUserERC1155: TestERC1155;
  let SwapParticipant: Deployment;
  let initiatorParticipant: SwapParticipant;
  let secondUserParticipant: SwapParticipant;
  let signers: Signer[];
  let appUser: SwapKiwi;
  let otherAppUser: SwapKiwi;
  let appUserAddress: string;
  let otherAppUserAddress: string;
  const VALID_APP_FEE = ethers.utils.parseEther("0.1");

  before(async () => {
    signers = await ethers.getSigners();
    ({ SwapKiwi, TestERC721, TestERC1155, SwapParticipant } = await deployments.fixture());

    swapKiwi = await ethers.getContractAt(SwapKiwi.abi, SwapKiwi.address, signers[0]) as SwapKiwi;

    appUserERC721 = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[2]) as TestERC721;
    otherAppUserERC721 = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[3]) as TestERC721;

    appUserERC1155 = await ethers.getContractAt(TestERC1155.abi, TestERC1155.address, signers[2]) as TestERC1155;
    otherAppUserERC1155 = await ethers.getContractAt(TestERC1155.abi, TestERC1155.address, signers[3]) as TestERC1155;

    initiatorParticipant = await ethers.getContractAt(SwapParticipant.abi, SwapParticipant.address, signers[2]) as SwapParticipant;
    secondUserParticipant = await ethers.getContractAt(SwapParticipant.abi, SwapParticipant.address, signers[3]) as SwapParticipant;

    appUser = new ethers.Contract(swapKiwi.address, SwapKiwi.abi, signers[2]) as SwapKiwi;
    otherAppUser = new ethers.Contract(swapKiwi.address, SwapKiwi.abi, signers[3]) as SwapKiwi;
    appUserAddress = await signers[2].getAddress();
    otherAppUserAddress = await signers[3].getAddress();
  });

  function getFilterName(eventName: string) {
    let filter: any;
    switch (eventName) {
      case "SwapExecuted":
        filter = swapKiwi.filters.SwapExecuted(null, null, null);
        break;
      case "SwapCanceled":
        filter = swapKiwi.filters.SwapCanceled(null, null);
        break;
      case "SwapProposed":
        filter = swapKiwi.filters.SwapProposed(null, null, null, null, null, null, null);
        break;
      case "SwapInitiated":
        filter = swapKiwi.filters.SwapInitiated(null, null, null, null, null, null, null);
      default: null
    }
    return filter;
  }

  async function getEventWithArgsFromLogs(txReceipt: TransactionReceipt, eventName: string): Promise<any | null> {
    if (txReceipt.logs) {
      const events = await swapKiwi.queryFilter(getFilterName(eventName), undefined);
      return events.map((e) => {
        if (e.event == eventName) {
          return {
            eventName: eventName,
            args: e.args
          }
        }
      }
      ).pop()
    }
    return null;
  }

  it("Should successfuly set app fee if caller is the owner", async function () {
    await swapKiwi.setAppFee(VALID_APP_FEE);
    expect((await swapKiwi.fee()).toString()).to.be.deep.equal(VALID_APP_FEE.toString());
  });

  it("Should fail to set app fee if caller is not owner", async function () {
    const nonOwnerContract = new ethers.Contract(SwapKiwi.address, SwapKiwi.abi, signers[6]) as SwapKiwi;

    await expect(nonOwnerContract.setAppFee(1000))
      .to.be.rejectedWith("Ownable: caller is not the owner");
  });

  it('Should fail to propose swap with invalid app fee', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      "SwapKiwi: Sent ETH amount needs to be more or equal application fee"
    );
  });

  it('Should fail to propose swap with different nft address and id length', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [13], [], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: NFT and ID arrays have to be same length"
    );
  });

  it('Should fail to propose swap with different nft address and amount length', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [], [5], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: NFT and AMOUNT arrays have to be same length"
    );
  });

  it('Should succesfully deposit NFT into escrow contract and emit "SwapProposed" event', async function () {
    const initiatorTokenIds = [25, 25];
    const initiatorTokenAmounts = [0, 50];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    expect(await appUserERC721.ownerOf(initiatorTokenIds[0])).to.be.deep.equal(appUserAddress);
    
    const erc1155_balance_beforeDeposit =  await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    expect(erc1155_balance_beforeDeposit.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");

    const erc1155_balance_AfterDeposit =  await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    const erc1155_balance_SwapKiwi = await appUserERC1155.balanceOf(swapKiwi.address, initiatorTokenIds[1]);

    // check if all values are emitted in event
    expect(logs.eventName).to.be.deep.equal("SwapProposed");
    expect(logs.args.from).to.be.deep.equal(appUserAddress);
    expect(logs.args.to).to.be.deep.equal(otherAppUserAddress);
    expect(logs.args.nftAddresses[0]).to.be.deep.equal(appUserERC721.address);
    expect(logs.args.nftIds[0].toString()).to.be.deep.equal("25");
    expect(logs.args.nftIds[1].toString()).to.be.deep.equal("25");
    expect(logs.args.nftAmounts[0].toString()).to.be.deep.equal("0");
    expect(logs.args.nftAmounts[1].toString()).to.be.deep.equal("50");
    expect(await appUserERC721.ownerOf(25)).to.be.deep.equal(swapKiwi.address);
    expect(erc1155_balance_AfterDeposit.toNumber()).to.be.deep.equal(0);
    expect(erc1155_balance_SwapKiwi.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
  });

  it('Should succesfully cancel swap by first user (after swap proposed) and emit "SwapCanceled" event', async function () {
    await appUserERC721.mint(appUserAddress, 140);
    await appUserERC721.approve(swapKiwi.address, 140);
    await appUserERC1155.mint(appUserAddress, 30, 50);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], [140, 30], [0, 50], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const user_erc1155BalanceBeforeCancel = await appUserERC1155.balanceOf(appUserAddress, 30);
    expect(user_erc1155BalanceBeforeCancel.toNumber()).to.be.deep.equal(0);
    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    const user_erc1155BalanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, 30);
    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that ERC721 and ERC1155 are returned to initial owner
    expect(await appUserERC721.ownerOf(140)).to.be.deep.equal(appUserAddress);
    expect(user_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(50);
  });

  it('Should succesfully cancel swap by second user (after swap proposed) and emit "SwapCanceled" event', async function () {
    const initiatorTokenIds = [141, 725];
    const initiatorTokenAmounts = [0, 50];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const user_erc1155BalanceBeforeCancel = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    expect(user_erc1155BalanceBeforeCancel.toNumber()).to.be.deep.equal(0);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    const user_erc1155BalanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that ERC721 and ERC1155 are returned to initial owner
    expect(await appUserERC721.ownerOf(initiatorTokenIds[0])).to.be.deep.equal(appUserAddress);
    expect(user_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
  });

  it('Should succesfully cancel swap by first user (after swap initiated) and emit "SwapCanceled" event', async function () {
    const initiatorTokenIds = [120, 923];
    const initiatorTokenAmounts = [0, 25];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const secondUserTokenIds = [130, 131, 47];
    const secondUserTokenAmounts = [0, 0, 50];

    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[0]);
    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[1]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[0]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[1]);
    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[2], secondUserTokenAmounts[2]);
    await otherAppUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address, otherAppUserERC721.address, otherAppUserERC1155.address],
      secondUserTokenIds,
      secondUserTokenAmounts,
      {
        value: VALID_APP_FEE
      }
    );

    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");

    const initiatorERC1155_923_balance = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    const secondUserERC1155_47_balance = await otherAppUserERC1155.balanceOf(otherAppUserAddress, secondUserTokenIds[2]);
    
    expect(initiatorERC1155_923_balance.toNumber()).to.be.deep.equal(0);
    expect(secondUserERC1155_47_balance.toNumber()).to.be.deep.equal(0);

    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    const initiatorERC1155_923_balanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    const secondUserERC1155_47_balanceAfterCancel = await otherAppUserERC1155.balanceOf(otherAppUserAddress, secondUserTokenIds[2]);

    expect(initiatorERC1155_923_balanceAfterCancel.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
    expect(secondUserERC1155_47_balanceAfterCancel.toNumber()).to.be.deep.equal(secondUserTokenAmounts[2]);

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserERC721.ownerOf(120)).to.be.deep.equal(appUserAddress);
    expect(await appUserERC721.ownerOf(130)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserERC721.ownerOf(131)).to.be.deep.equal(otherAppUserAddress);
  });

  it('Should succesfully cancel swap by second user (after swap initiated) and emit "SwapCanceled" event', async function () {
    const initiatorTokenIds = [121, 47];
    const initiatorTokenAmounts = [0, 25];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const secondUserTokenIds = [135, 136, 71];
    const secondUserTokenAmounts = [0, 0, 25];

    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[0]);
    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[1]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[0]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[1]);
    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[2], secondUserTokenAmounts[2]);
    await otherAppUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address, otherAppUserERC721.address, otherAppUserERC1155.address],
      secondUserTokenIds,
      secondUserTokenAmounts,
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");

    const initiatorERC1155_47_balance = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    const secondUserERC1155_71_balance = await otherAppUserERC1155.balanceOf(otherAppUserAddress, secondUserTokenIds[2]);
    
    expect(initiatorERC1155_47_balance.toNumber()).to.be.deep.equal(0);
    expect(secondUserERC1155_71_balance.toNumber()).to.be.deep.equal(0);

    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    const initiatorERC1155_47_balanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);
    const secondUserERC1155_71_balanceAfterCancel = await otherAppUserERC1155.balanceOf(otherAppUserAddress, secondUserTokenIds[2]);

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserERC721.ownerOf(121)).to.be.deep.equal(appUserAddress);
    expect(await appUserERC721.ownerOf(135)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserERC721.ownerOf(136)).to.be.deep.equal(otherAppUserAddress);
    expect(initiatorERC1155_47_balanceAfterCancel.toNumber()).to.be.deep.equal(secondUserTokenAmounts[2]);
    expect(secondUserERC1155_71_balanceAfterCancel.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
  });

  it('Should succesfully cancel swap created with ether value', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    const initiatorTokenIds = [430, 431];
    const initiatorTokenAmounts = [0, 25];

    await appUserERC721.mint(appUserAddress, 430);
    await appUserERC721.approve(swapKiwi.address, 430);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE.add(parseEther("20"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserERC721.mint(otherAppUserAddress, 431);
    await otherAppUserERC721.approve(swapKiwi.address, 431);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address],
      [431], [0],
      {
        value: VALID_APP_FEE.add(parseEther("10"))
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    const erc1155_431_initiatorBalance = await appUserERC1155.balanceOf(appUserAddress, initiatorTokenIds[1]);

    expect(await appUserERC721.ownerOf(430)).to.be.deep.equal(appUserAddress);
    expect(await appUserERC721.ownerOf(431)).to.be.deep.equal(otherAppUserAddress);
    expect(erc1155_431_initiatorBalance.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
    expect(firstUserBalance.sub(await appUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub(await otherAppUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should fail to initiate swap if swap canceled', async function () {
    const initiatorTokenIds = [170, 171];
    const initiatorTokenAmounts = [0, 90];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    await cancelTx.wait(1);

    await otherAppUserERC721.mint(otherAppUserAddress, 301);
    await otherAppUserERC721.approve(swapKiwi.address, 301);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserERC721.address], [301], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      `SwapKiwi: caller is not swap participator`
    );
  });

  it('Should fail to initiate swap with invalid app fee', async function () {
    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(parseEther("0.1"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [], [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      `SwapKiwi: Sent ETH amount needs to be more or equal application fee`
    );
  });

  it('Should fail to initiate swap twice', async function () {
    const initiatorTokenIds = [189, 190];
    const initiatorTokenAmounts = [0, 75];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUserERC721.mint(otherAppUserAddress, 302);
    await otherAppUserERC721.approve(swapKiwi.address, 302);
    await otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserERC721.address], [302], [0], {
      value: VALID_APP_FEE
    })

    await otherAppUserERC721.mint(otherAppUserAddress, 303);
    await otherAppUserERC721.approve(swapKiwi.address, 303);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserERC721.address], [303], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to initiate swap twice if proposed only with ether', async function () {
    const initiatorTokenIds = [1732, 1733];
    const initiatorTokenAmounts = [0, 100];

    await appUserERC721.mint(appUserAddress, 1732);
    await appUserERC721.approve(swapKiwi.address, 1732);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUser.initiateSwap(swapIdFromLogs, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("0.25"))
    })


    await otherAppUserERC721.mint(otherAppUserAddress, 1733);
    await otherAppUserERC721.approve(swapKiwi.address, 1733);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserERC721.address], [1733], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to cancel swap twice', async function () {
    const initiatorTokenIds = [200, 201];
    const initiatorTokenAmounts = [0, 2];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserERC721.ownerOf(200)).to.be.deep.equal(appUserAddress);

    await expect(appUser.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant"
    );
  });

  it("Should fail to cancel swap if user is not a swap participant", async function () {
    const nonSwapParticipant = new ethers.Contract(SwapKiwi.address, SwapKiwi.abi, signers[6]) as SwapKiwi;

    const initiatorTokenIds = [70, 71];
    const initiatorTokenAmounts = [0, 75];

    // first user NFT minting and swap deposit into SwapKiwi
    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(nonSwapParticipant.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant");
  });

  it("Should fail to accept swap if second user didn't add NFTs or ether", async function () {
    const initiatorTokenIds = [2000, 2001];
    const initiatorTokenAmounts = [0, 10];

    // first user NFT minting and swap deposit into SwapKiwi
    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(appUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't accept swap, both participants didn't add NFTs");
  });

  it('Should fail to accept swap if not swap initiator', async function () {
    await appUserERC721.mint(appUserAddress, 2100);
    await appUserERC721.approve(swapKiwi.address, 2100);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address], [2100], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    await expect(otherAppUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: caller is not swap initiator"
    );
  });

  it('Should successfully execute NFT - NFT swap', async function () {
    // first user NFT minting and swap deposit into SwapKiwi
    const initiatorNftIds = [85, 86, 55];
    const initiatorNftAmounts = [0, 0, 10];
    const secondUserNftIds = [87, 88, 56];
    const secondUserNftAmounts = [0, 0, 15];

    await appUserERC721.mint(appUserAddress, initiatorNftIds[0]);
    await appUserERC721.mint(appUserAddress, initiatorNftIds[1]);
    await appUserERC721.approve(swapKiwi.address, initiatorNftIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorNftIds[1]);
    await appUserERC1155.mint(appUserAddress, initiatorNftIds[2], initiatorNftAmounts[2]);
    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC721.address, appUserERC1155.address], initiatorNftIds, initiatorNftAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const swap_erc1155_55_balance = await appUserERC1155.balanceOf(swapKiwi.address, 55);

    // check that first user NFTs are deposited into SwapKiwi
    expect(await appUserERC721.ownerOf(85)).to.be.deep.equal(swapKiwi.address);
    expect(await appUserERC721.ownerOf(86)).to.be.deep.equal(swapKiwi.address);
    expect(swap_erc1155_55_balance.toNumber()).to.be.deep.equal(initiatorNftAmounts[2]);

    // second user NFT minting and swap deposit into SwapKiwi
    await otherAppUserERC721.mint(otherAppUserAddress, secondUserNftIds[0]);
    await otherAppUserERC721.mint(otherAppUserAddress, secondUserNftIds[1]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserNftIds[0]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserNftIds[1]);
    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserNftIds[2], secondUserNftAmounts[2]);
    await otherAppUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address, otherAppUserERC721.address, otherAppUserERC1155.address],
      secondUserNftIds,
      secondUserNftAmounts,
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    
    const swap_erc1155_56_balance = await otherAppUserERC1155.balanceOf(swapKiwi.address, secondUserNftIds[2]);

    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);
    
    // check that second user NFTs are deposited into SwapKiwi
    expect(await otherAppUserERC721.ownerOf(87)).to.be.deep.equal(swapKiwi.address);
    expect(await otherAppUserERC721.ownerOf(88)).to.be.deep.equal(swapKiwi.address);
    expect(swap_erc1155_56_balance.toNumber()).to.be.deep.equal(secondUserNftAmounts[2]);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    const acceptSwapTxReceipt = await acceptSwapTx.wait(1);
    const acceptSwapLogs = await getEventWithArgsFromLogs(acceptSwapTxReceipt, "SwapExecuted");

    // check if all values are emitted in "SwapExecuted" event
    expect(acceptSwapLogs.eventName).to.be.deep.equal("SwapExecuted");
    expect(acceptSwapLogs.args.from).to.be.deep.equal(appUserAddress);
    expect(acceptSwapLogs.args.to).to.be.deep.equal(otherAppUserAddress);
    // check that NFTs are transfered from SwapKiwi to participants - same address because both have same signer

    expect(await otherAppUserERC721.ownerOf(85)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserERC721.ownerOf(86)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserERC721.ownerOf(87)).to.be.deep.equal(appUserAddress);
    expect(await appUserERC721.ownerOf(88)).to.be.deep.equal(appUserAddress);

    const initiator_erc1155_56_balance = await otherAppUserERC1155.balanceOf(appUserAddress, secondUserNftIds[2]);
    expect(initiator_erc1155_56_balance.toNumber()).to.be.deep.equal(secondUserNftAmounts[2]);

    const secondUser_erc1155_55_balance = await otherAppUserERC1155.balanceOf(otherAppUserAddress, initiatorNftIds[2]);
    expect(secondUser_erc1155_55_balance.toNumber()).to.be.deep.equal(initiatorNftAmounts[2]);
  });

  it('Should successfully execute NFT + ether - NFT + ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    const initiatorTokenIds = [375, 1376, 1377];
    const initiatorTokenAmounts = [0, 10, 20];

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[2], initiatorTokenAmounts[2]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const secondUserTokenIds = [376, 2376, 2377];
    const secondUserTokenAmounts = [0, 50, 60];

    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[0]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[0]);

    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[1], secondUserTokenAmounts[1]);
    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[2], secondUserTokenAmounts[2]);

    await otherAppUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address, otherAppUserERC1155.address, otherAppUserERC1155.address],
      secondUserTokenIds,
      secondUserTokenAmounts,
      {
        value: VALID_APP_FEE.add(parseEther("25"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    const erc1155_2376_initiatorBalance = await otherAppUserERC1155.balanceOf(appUserAddress, secondUserTokenIds[1]);
    const erc1155_2377_initiatorBalance = await otherAppUserERC1155.balanceOf(appUserAddress, secondUserTokenIds[2]);

    const erc1155_1376_secondUserBalance = await appUserERC1155.balanceOf(otherAppUserAddress, initiatorTokenIds[1]);
    const erc1155_1377_secondUserBalance = await appUserERC1155.balanceOf(otherAppUserAddress, initiatorTokenIds[2]);

    expect(await appUserERC721.ownerOf(375)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserERC721.ownerOf(376)).to.be.deep.equal(appUserAddress);
    expect(erc1155_2376_initiatorBalance.toNumber()).to.be.deep.equal(secondUserTokenAmounts[1]);
    expect(erc1155_2377_initiatorBalance.toNumber()).to.be.deep.equal(secondUserTokenAmounts[2]);
    expect(erc1155_1376_secondUserBalance.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
    expect(erc1155_1377_secondUserBalance.toNumber()).to.be.deep.equal(initiatorTokenAmounts[2]);
    expect(firstUserBalance.sub((await appUser.signer.getBalance()).add(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub((await otherAppUser.signer.getBalance()).sub(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute ether - NFT swap', async function () {
    const secondUserBalance = await otherAppUser.signer.getBalance();

    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const secondUserTokenIds = [1800, 1801, 1802];
    const secondUserTokenAmounts = [0, 50, 60];

    await otherAppUserERC721.mint(otherAppUserAddress, secondUserTokenIds[0]);
    await otherAppUserERC721.approve(swapKiwi.address, secondUserTokenIds[0]);

    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[1], secondUserTokenAmounts[1]);
    await otherAppUserERC1155.mint(otherAppUserAddress, secondUserTokenIds[2], secondUserTokenAmounts[2]);

    await otherAppUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserERC721.address, otherAppUserERC1155.address, otherAppUserERC1155.address],
      secondUserTokenIds,
      secondUserTokenAmounts,
      {
        value: VALID_APP_FEE
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    const erc1155_1801_initiatorBalance = await otherAppUserERC1155.balanceOf(appUserAddress, secondUserTokenIds[1]);
    const erc1155_1802_initiatorBalance = await otherAppUserERC1155.balanceOf(appUserAddress, secondUserTokenIds[2]);

    expect(await otherAppUserERC721.ownerOf(1800)).to.be.deep.equal(appUserAddress);
    expect(erc1155_1801_initiatorBalance.toNumber()).to.be.deep.equal(secondUserTokenAmounts[1]);
    expect(erc1155_1802_initiatorBalance.toNumber()).to.be.deep.equal(secondUserTokenAmounts[2]);
    expect(
      (
        await otherAppUser.signer.getBalance()
      ).sub(secondUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute NFT - ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();

    const initiatorTokenIds = [1822, 1823, 1825];
    const initiatorTokenAmounts = [0, 10, 20];

    await appUserERC721.mint(appUserAddress, initiatorTokenIds[0]);
    await appUserERC721.approve(swapKiwi.address, initiatorTokenIds[0]);

    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[1], initiatorTokenAmounts[1]);
    await appUserERC1155.mint(appUserAddress, initiatorTokenIds[2], initiatorTokenAmounts[2]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserERC721.address, appUserERC1155.address, appUserERC1155.address], initiatorTokenIds, initiatorTokenAmounts, {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    const erc1155_1823_otherUserBalance = await appUserERC1155.balanceOf(otherAppUserAddress, initiatorTokenIds[1]);
    const erc1155_1825_otherUserBalance = await appUserERC1155.balanceOf(otherAppUserAddress, initiatorTokenIds[2]);

    expect(await appUserERC721.ownerOf(initiatorTokenIds[0])).to.be.deep.equal(otherAppUserAddress);
    expect(erc1155_1823_otherUserBalance.toNumber()).to.be.deep.equal(initiatorTokenAmounts[1]);
    expect(erc1155_1825_otherUserBalance.toNumber()).to.be.deep.equal(initiatorTokenAmounts[2]);
    expect(
      (
        await appUser.signer.getBalance()
      ).sub(firstUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it("Should successfully withdraw only collected fees", async function () {
    await swapKiwi.withdrawEther(await signers[7].getAddress());

    const tx1 = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt1 = await tx1.wait(1);
    const logs1 = await getEventWithArgsFromLogs(txReceipt1, "SwapProposed");
    const swapIdFromLogs1 = Number(logs1.args.swapId.toString());
    const initiateSwapTx1 = await otherAppUser.initiateSwap(
      swapIdFromLogs1,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx1.wait(1);
    const acceptSwapTx1 = await appUser.acceptSwap(swapIdFromLogs1);
    await acceptSwapTx1.wait(1);
    const tx2 = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt2 = await tx2.wait(1);
    const logs2 = await getEventWithArgsFromLogs(txReceipt2, "SwapProposed");
    const swapIdFromLogs = Number(logs2.args.swapId.toString());
    const initiateSwapTx2 = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx2.wait(1);

    await swapKiwi.withdrawEther(appUserERC721.address)

    expect((await ethers.provider.getBalance(appUserERC721.address)).toString())
      .to.be.deep.equal(VALID_APP_FEE.mul(4).toString())
  });

  it("Should fail to withdraw collected fees if not owner", async function () {
    await expect(appUser.withdrawEther(appUser.address))
      .to.be.rejectedWith(
        "Ownable: caller is not the owner");
  });

  it("Should fail to withdraw collected fees if sent to zero address", async function () {
    await expect(swapKiwi.withdrawEther("0x0000000000000000000000000000000000000000"))
      .to.be.rejectedWith("SwapKiwi: transfer to the zero address");
  });

  it("The initiator should get their parts even if the common cancelling(part) is failed. And then the second user can get its part through a single side cancel", async function () {
    const tokenIds = [1827, 1828];
    const tokenAmounts = [10, 20];

    const secondUserBalance = await secondUserParticipant.signer.getBalance();

    await appUserERC1155.mint(appUserAddress, tokenIds[0], tokenAmounts[0]);
    await otherAppUserERC1155.mint(secondUserParticipant.address, tokenIds[1], tokenAmounts[1]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);
    await secondUserParticipant.setSwap(swapKiwi.address);

    const tx = await appUser.proposeSwap(secondUserParticipant.address, [appUserERC1155.address], [tokenIds[0]], [tokenAmounts[0]], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await secondUserParticipant.initiateSwap(swapIdFromLogs, [otherAppUserERC1155.address], [tokenIds[1]], [tokenAmounts[1]], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });

    await secondUserParticipant.setCounter(10);

    await appUser.cancelSwap(swapIdFromLogs);

    const initiator_erc1155BalanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, tokenIds[0]);
    // check that ERC721 and ERC1155 are returned to initial owner
    expect(initiator_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[0]);
  
    await secondUserParticipant.setCounter(0);
    await secondUserParticipant.cancelSwapBySecondUser(swapIdFromLogs);
    const secondUser_erc1155BalanceAfterCancel = await otherAppUserERC1155.balanceOf(secondUserParticipant.address, tokenIds[1]);
    expect(secondUser_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[1]);
    expect(secondUserBalance.sub(await secondUserParticipant.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
  });

  it("The initiator should get their part even if the common cancelling(full) is failed. And then the second user can get its part through a single side cancel", async function () {
    const tokenIds = [11827, 11828];
    const tokenAmounts = [10, 20];

    const secondUserBalance = await secondUserParticipant.signer.getBalance();

    await appUserERC1155.mint(initiatorParticipant.address, tokenIds[0], tokenAmounts[0]);
    await otherAppUserERC1155.mint(secondUserParticipant.address, tokenIds[1], tokenAmounts[1]);

    await initiatorParticipant.setSwap(swapKiwi.address);
    await secondUserParticipant.setSwap(swapKiwi.address);

    const tx = await initiatorParticipant.proposeSwap(secondUserParticipant.address, [appUserERC1155.address], [tokenIds[0]], [tokenAmounts[0]], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await secondUserParticipant.initiateSwap(swapIdFromLogs, [otherAppUserERC1155.address], [tokenIds[1]], [tokenAmounts[1]], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });

    await initiatorParticipant.setCounter(10);
    await expect(initiatorParticipant.cancelSwap(swapIdFromLogs))
      .to.be.rejectedWith("The malicious onERC1155Received contract");

    const initiator_erc1155BalanceAfterCancel = await appUserERC1155.balanceOf(initiatorParticipant.address, tokenIds[0]);
    // check that ERC721 and ERC1155 are returned to initial owner
    expect(initiator_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(0);
  
    await secondUserParticipant.setCounter(0);
    await secondUserParticipant.cancelSwapBySecondUser(swapIdFromLogs);
    const secondUser_erc1155BalanceAfterCancel = await otherAppUserERC1155.balanceOf(secondUserParticipant.address, tokenIds[1]);
    expect(secondUser_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[1]);
    expect(secondUserBalance.sub(await secondUserParticipant.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
  });

  it("The second user can get its part through a single side cancel. After that, the initiator can get its part through the common cancel", async function () {
    const tokenIds = [1227, 1228];
    const tokenAmounts = [10, 20];

    const secondUserBalance = await secondUserParticipant.signer.getBalance();

    await appUserERC1155.mint(appUserAddress, tokenIds[0], tokenAmounts[0]);
    await otherAppUserERC1155.mint(secondUserParticipant.address, tokenIds[1], tokenAmounts[1]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);
    await secondUserParticipant.setSwap(swapKiwi.address);

    const tx = await appUser.proposeSwap(secondUserParticipant.address, [appUserERC1155.address], [tokenIds[0]], [tokenAmounts[0]], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await secondUserParticipant.initiateSwap(swapIdFromLogs, [otherAppUserERC1155.address], [tokenIds[1]], [tokenAmounts[1]], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });

    await secondUserParticipant.cancelSwapBySecondUser(swapIdFromLogs);
    const secondUser_erc1155BalanceAfterCancel = await otherAppUserERC1155.balanceOf(secondUserParticipant.address, tokenIds[1]);
    expect(secondUser_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[1]);
    expect(secondUserBalance.sub(await secondUserParticipant.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);

    await appUser.cancelSwap(swapIdFromLogs);
    const initiator_erc1155BalanceAfterCancel = await appUserERC1155.balanceOf(appUserAddress, tokenIds[0]);
    // check that ERC721 and ERC1155 are returned to initial owner
    expect(initiator_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[0]);
  });

  it("After the second user does a single side cancel, the swap should be failed", async function () {
    const tokenIds = [1027, 1028];
    const tokenAmounts = [10, 20];

    const secondUserBalance = await secondUserParticipant.signer.getBalance();

    await appUserERC1155.mint(appUserAddress, tokenIds[0], tokenAmounts[0]);
    await otherAppUserERC1155.mint(secondUserParticipant.address, tokenIds[1], tokenAmounts[1]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);
    await secondUserParticipant.setSwap(swapKiwi.address);

    const tx = await appUser.proposeSwap(secondUserParticipant.address, [appUserERC1155.address], [tokenIds[0]], [tokenAmounts[0]], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await secondUserParticipant.initiateSwap(swapIdFromLogs, [otherAppUserERC1155.address], [tokenIds[1]], [tokenAmounts[1]], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });

    await secondUserParticipant.cancelSwapBySecondUser(swapIdFromLogs);
    const secondUser_erc1155BalanceAfterCancel = await otherAppUserERC1155.balanceOf(secondUserParticipant.address, tokenIds[1]);
    expect(secondUser_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[1]);
    expect(secondUserBalance.sub(await secondUserParticipant.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);

    await expect(appUser.acceptSwap(swapIdFromLogs))
      .to.be.rejectedWith("SwapKiwi: Can't accept swap, both participants didn't add NFTs");
  });

  it("etherLocked amount should not be changed if eth transfer to the second user is failed when common cancel", async function () {
    const tokenIds = [18827, 18828];
    const tokenAmounts = [10, 20];

    const secondUserBalance = await secondUserParticipant.signer.getBalance();

    await appUserERC1155.mint(appUserAddress, tokenIds[0], tokenAmounts[0]);
    await otherAppUserERC1155.mint(secondUserParticipant.address, tokenIds[1], tokenAmounts[1]);

    await appUserERC1155.setApprovalForAll(swapKiwi.address, true);
    await secondUserParticipant.setSwap(swapKiwi.address);

    const tx = await appUser.proposeSwap(secondUserParticipant.address, [appUserERC1155.address], [tokenIds[0]], [tokenAmounts[0]], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await secondUserParticipant.initiateSwap(swapIdFromLogs, [otherAppUserERC1155.address], [tokenIds[1]], [tokenAmounts[1]], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });

    const locked = await appUser.etherLocked();

    await secondUserParticipant.setCounter2(10);
    await appUser.cancelSwap(swapIdFromLogs);

    const lockedAfterFailed = await appUser.etherLocked();

    expect(lockedAfterFailed.toString()).to.be.deep.equal(locked.toString());
    const secondUser_erc1155BalanceAfterCancel = await otherAppUserERC1155.balanceOf(secondUserParticipant.address, tokenIds[1]);
    expect(secondUser_erc1155BalanceAfterCancel.toNumber()).to.be.deep.equal(tokenAmounts[1]);
    expect(secondUserBalance.sub(await secondUserParticipant.signer.getBalance()).gt(parseEther("50"))).to.be.equal(true);
  });
});
Example #4
Source File: swapKiwiV1.test.ts    From swap.kiwi with GNU General Public License v3.0 5 votes vote down vote up
describe("SwapKiwiV1", async function () {
  let SwapKiwiV1: Deployment;
  let swapKiwi: SwapKiwiV1;
  let TestERC721: Deployment;
  let appUserNFT: TestERC721;
  let otherAppUserNFT: TestERC721;
  let signers: Signer[];
  let appUser: SwapKiwiV1;
  let otherAppUser: SwapKiwiV1;
  let appUserAddress: string;
  let otherAppUserAddress: string;
  const VALID_APP_FEE = ethers.utils.parseEther("0.1");

  before(async () => {
    signers = await ethers.getSigners();
    ({ SwapKiwiV1, TestERC721 } = await deployments.fixture());
    swapKiwi = await ethers.getContractAt(SwapKiwiV1.abi, SwapKiwiV1.address, signers[0]) as SwapKiwiV1;

    appUserNFT = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[2]) as TestERC721;
    otherAppUserNFT = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[3]) as TestERC721;

    appUser = new ethers.Contract(swapKiwi.address, SwapKiwiV1.abi, signers[2]) as SwapKiwiV1;
    otherAppUser = new ethers.Contract(swapKiwi.address, SwapKiwiV1.abi, signers[3]) as SwapKiwiV1;
    appUserAddress = await signers[2].getAddress();
    otherAppUserAddress = await signers[3].getAddress();
  });

  function getFilterName(eventName: string) {
    let filter: any;
    switch (eventName) {
      case "SwapExecuted":
        filter = swapKiwi.filters.SwapExecuted(null, null, null);
        break;
      case "SwapCanceled":
        filter = swapKiwi.filters.SwapCanceled(null, null);
        break;
      case "SwapProposed":
        filter = swapKiwi.filters.SwapProposed(null, null, null, null, null, null);
        break;
      case "SwapInitiated":
        filter = swapKiwi.filters.SwapInitiated(null, null, null, null, null, null);
      default: null
    }
    return filter;
  }

  async function getEventWithArgsFromLogs(txReceipt: TransactionReceipt, eventName: string): Promise<any | null> {
    if (txReceipt.logs) {
      const events = await swapKiwi.queryFilter(getFilterName(eventName), undefined);
      return events.map((e) => {
        if (e.event == eventName) {
          return {
            eventName: eventName,
            args: e.args
          }
        }
      }
      ).pop()
    }
    return null;
  }

  it("Should successfuly set app fee if caller is the owner", async function () {
    await swapKiwi.setAppFee(VALID_APP_FEE);
    expect((await swapKiwi.fee()).toString()).to.be.deep.equal(VALID_APP_FEE.toString());
  });

  it("Should fail to set app fee if caller is not owner", async function () {
    const nonOwnerContract = new ethers.Contract(SwapKiwiV1.address, SwapKiwiV1.abi, signers[6]) as SwapKiwiV1;

    await expect(nonOwnerContract.setAppFee(1000))
      .to.be.rejectedWith("Ownable: caller is not the owner");
  });

  it('Should fail to propose swap with invalid app fee', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      "SwapKiwi: Sent ETH amount needs to be more or equal application fee"
    );
  });

  it('Should fail to propose swap with different nft address and if length', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [13], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: NFT and ID arrays have to be same length"
    );
  });

  it('Should succesfully deposit NFT into escrow contract and emit "SwapProposed" event', async function () {
    await appUserNFT.mint(appUserAddress, 25);
    await appUserNFT.approve(swapKiwi.address, 25);
    expect(await appUserNFT.ownerOf(25)).to.be.deep.equal(appUserAddress);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [25], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");

    // check if all values are emitted in event
    expect(logs.eventName).to.be.deep.equal("SwapProposed");
    expect(logs.args.from).to.be.deep.equal(appUserAddress);
    expect(logs.args.to).to.be.deep.equal(otherAppUserAddress);
    expect(logs.args.nftAddresses[0]).to.be.deep.equal(appUserNFT.address);
    expect(logs.args.nftIds[0].toString()).to.be.deep.equal("25");
    expect(await appUserNFT.ownerOf(25)).to.be.deep.equal(swapKiwi.address);
  });

  it('Should succesfully cancel swap by first user (after swap proposed) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 140);
    await appUserNFT.approve(swapKiwi.address, 140);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [140], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(140)).to.be.deep.equal(appUserAddress);
  });

  it('Should succesfully cancel swap by second user (after swap proposed) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 141);
    await appUserNFT.approve(swapKiwi.address, 141);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [141], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(141)).to.be.deep.equal(appUserAddress);
  });

  it('Should succesfully cancel swap by first user (after swap initiated) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 120);
    await appUserNFT.approve(swapKiwi.address, 120);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [120], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 130);
    await otherAppUserNFT.mint(otherAppUserAddress, 131);
    await otherAppUserNFT.approve(swapKiwi.address, 130);
    await otherAppUserNFT.approve(swapKiwi.address, 131);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [130, 131],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserNFT.ownerOf(120)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(130)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(131)).to.be.deep.equal(otherAppUserAddress);
  });

  it('Should succesfully cancel swap by second user (after swap initiated) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 121);
    await appUserNFT.approve(swapKiwi.address, 121);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [121], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 135);
    await otherAppUserNFT.mint(otherAppUserAddress, 136);
    await otherAppUserNFT.approve(swapKiwi.address, 135);
    await otherAppUserNFT.approve(swapKiwi.address, 136);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [135, 136],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserNFT.ownerOf(121)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(135)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(136)).to.be.deep.equal(otherAppUserAddress);
  });

  it('Should succesfully cancel swap created with ether value', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 430);
    await appUserNFT.approve(swapKiwi.address, 430);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [430], {
      value: VALID_APP_FEE.add(parseEther("20"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 431);
    await otherAppUserNFT.approve(swapKiwi.address, 431);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [431],
      {
        value: VALID_APP_FEE.add(parseEther("10"))
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    expect(await appUserNFT.ownerOf(430)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(431)).to.be.deep.equal(otherAppUserAddress);
    expect(firstUserBalance.sub(await appUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub(await otherAppUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should fail to initiate swap if swap canceled', async function () {
    await appUserNFT.mint(appUserAddress, 170);
    await appUserNFT.approve(swapKiwi.address, 170);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [170], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    await cancelTx.wait(1);

    await otherAppUserNFT.mint(otherAppUserAddress, 301);
    await otherAppUserNFT.approve(swapKiwi.address, 301);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [301], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      `SwapKiwi: caller is not swap participator`
    );
  });

  it('Should fail to initiate swap with invalid app fee', async function () {
    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], {
      value: VALID_APP_FEE.add(parseEther("0.1"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      `SwapKiwi: Sent ETH amount needs to be more or equal application fee`
    );
  });

  it('Should fail to initiate swap twice', async function () {
    await appUserNFT.mint(appUserAddress, 189);
    await appUserNFT.approve(swapKiwi.address, 189);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [189], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUserNFT.mint(otherAppUserAddress, 302);
    await otherAppUserNFT.approve(swapKiwi.address, 302);
    await otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [302], {
      value: VALID_APP_FEE
    })


    await otherAppUserNFT.mint(otherAppUserAddress, 303);
    await otherAppUserNFT.approve(swapKiwi.address, 303);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [303], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to initiate swap twice if proposed only with ether', async function () {
    await appUserNFT.mint(appUserAddress, 1732);
    await appUserNFT.approve(swapKiwi.address, 1732);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [1732], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUser.initiateSwap(swapIdFromLogs, [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("0.25"))
    })


    await otherAppUserNFT.mint(otherAppUserAddress, 1733);
    await otherAppUserNFT.approve(swapKiwi.address, 1733);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [1733], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to cancel swap twice', async function () {
    await appUserNFT.mint(appUserAddress, 200);
    await appUserNFT.approve(swapKiwi.address, 200);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [200], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(200)).to.be.deep.equal(appUserAddress);

    await expect(appUser.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant"
    );
  });

  it("Should fail to cancel swap if user is not a swap participant", async function () {
    const nonSwapParticipant = new ethers.Contract(SwapKiwiV1.address, SwapKiwiV1.abi, signers[6]) as SwapKiwiV1;

    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 70);
    await appUserNFT.approve(swapKiwi.address, 70);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [70], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(nonSwapParticipant.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant");
  });

  it("Should fail to accept swap if second user didn't add NFTs or ether", async function () {
    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 2000);
    await appUserNFT.approve(swapKiwi.address, 2000);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [2000], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(appUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't accept swap, both participants didn't add NFTs");
  });

  it('Should fail to accept swap if not swap initiator', async function () {
    await appUserNFT.mint(appUserAddress, 2100);
    await appUserNFT.approve(swapKiwi.address, 2100);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [2100], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    await expect(otherAppUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: caller is not swap initiator"
    );
  });

  it('Should successfully execute NFT - NFT swap', async function () {
    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 85);
    await appUserNFT.mint(appUserAddress, 86);
    await appUserNFT.approve(swapKiwi.address, 85);
    await appUserNFT.approve(swapKiwi.address, 86);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address, appUserNFT.address], [85, 86], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    // check that first user NFTs are deposited into SwapKiwi
    expect(await appUserNFT.ownerOf(85)).to.be.deep.equal(swapKiwi.address);
    expect(await appUserNFT.ownerOf(86)).to.be.deep.equal(swapKiwi.address);

    // second user NFT minting and swap deposit into SwapKiwi
    await otherAppUserNFT.mint(otherAppUserAddress, 87);
    await otherAppUserNFT.mint(otherAppUserAddress, 88);
    await otherAppUserNFT.approve(swapKiwi.address, 87);
    await otherAppUserNFT.approve(swapKiwi.address, 88);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [87, 88],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    // check that second user NFTs are deposited into SwapKiwi
    expect(await otherAppUserNFT.ownerOf(87)).to.be.deep.equal(swapKiwi.address);
    expect(await otherAppUserNFT.ownerOf(88)).to.be.deep.equal(swapKiwi.address);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    const acceptSwapTxReceipt = await acceptSwapTx.wait(1);
    const acceptSwapLogs = await getEventWithArgsFromLogs(acceptSwapTxReceipt, "SwapExecuted");

    // check if all values are emitted in "SwapExecuted" event
    expect(acceptSwapLogs.eventName).to.be.deep.equal("SwapExecuted");
    expect(acceptSwapLogs.args.from).to.be.deep.equal(appUserAddress);
    expect(acceptSwapLogs.args.to).to.be.deep.equal(otherAppUserAddress);
    // check that NFTs are transfered from SwapKiwi to participants - same address because both have same signer

    expect(await otherAppUserNFT.ownerOf(85)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserNFT.ownerOf(86)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(87)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(88)).to.be.deep.equal(appUserAddress);
  });

  it('Should successfully execute NFT + ether - NFT + ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 375);
    await appUserNFT.approve(swapKiwi.address, 375);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [375], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 376);
    await otherAppUserNFT.approve(swapKiwi.address, 376);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [376],
      {
        value: VALID_APP_FEE.add(parseEther("25"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await appUserNFT.ownerOf(375)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserNFT.ownerOf(376)).to.be.deep.equal(appUserAddress);
    expect(firstUserBalance.sub((await appUser.signer.getBalance()).add(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub((await otherAppUser.signer.getBalance()).sub(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute ether - NFT swap', async function () {
    const secondUserBalance = await otherAppUser.signer.getBalance();

    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 1800);
    await otherAppUserNFT.approve(swapKiwi.address, 1800);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [1800],
      {
        value: VALID_APP_FEE
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await otherAppUserNFT.ownerOf(1800)).to.be.deep.equal(appUserAddress);
    expect(
      (
        await otherAppUser.signer.getBalance()
      ).sub(secondUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute NFT - ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 1822);
    await appUserNFT.approve(swapKiwi.address, 1822);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [1822], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await appUserNFT.ownerOf(1822)).to.be.deep.equal(otherAppUserAddress);
    expect(
      (
        await appUser.signer.getBalance()
      ).sub(firstUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it("Should successfully withdraw only collected fees", async function () {
    await swapKiwi.withdrawEther(await signers[7].getAddress());

    const tx1 = await appUser.proposeSwap(otherAppUserAddress, [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt1 = await tx1.wait(1);
    const logs1 = await getEventWithArgsFromLogs(txReceipt1, "SwapProposed");
    const swapIdFromLogs1 = Number(logs1.args.swapId.toString());
    const initiateSwapTx1 = await otherAppUser.initiateSwap(
      swapIdFromLogs1,
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx1.wait(1);
    const acceptSwapTx1 = await appUser.acceptSwap(swapIdFromLogs1);
    await acceptSwapTx1.wait(1);
    const tx2 = await appUser.proposeSwap(otherAppUserAddress, [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt2 = await tx2.wait(1);
    const logs2 = await getEventWithArgsFromLogs(txReceipt2, "SwapProposed");
    const swapIdFromLogs = Number(logs2.args.swapId.toString());
    const initiateSwapTx2 = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx2.wait(1);

    await swapKiwi.withdrawEther(appUserNFT.address)

    expect((await ethers.provider.getBalance(appUserNFT.address)).toString())
      .to.be.deep.equal(VALID_APP_FEE.mul(4).toString())
  });

  it("Should fail to withdraw collected fees if not owner", async function () {
    await expect(appUser.withdrawEther(appUser.address))
      .to.be.rejectedWith(
        "Ownable: caller is not the owner");
  });

  it("Should fail to withdraw collected fees if sent to zero address", async function () {
    await expect(swapKiwi.withdrawEther("0x0000000000000000000000000000000000000000"))
      .to.be.rejectedWith("SwapKiwi: transfer to the zero address");
  });
});
Example #5
Source File: swapKiwiWithOnlyERC721.test.ts    From swap.kiwi with GNU General Public License v3.0 5 votes vote down vote up
describe("SwapKiwi-With only ERC721 to compare SwapKiwiV1", async function () {
  let SwapKiwi: Deployment;
  let swapKiwi: SwapKiwi;
  let TestERC721: Deployment;
  let appUserNFT: TestERC721;
  let otherAppUserNFT: TestERC721;
  let signers: Signer[];
  let appUser: SwapKiwi;
  let otherAppUser: SwapKiwi;
  let appUserAddress: string;
  let otherAppUserAddress: string;
  const VALID_APP_FEE = ethers.utils.parseEther("0.1");

  before(async () => {
    signers = await ethers.getSigners();
    ({ SwapKiwi, TestERC721 } = await deployments.fixture());
    swapKiwi = await ethers.getContractAt(SwapKiwi.abi, SwapKiwi.address, signers[0]) as SwapKiwi;

    appUserNFT = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[2]) as TestERC721;
    otherAppUserNFT = await ethers.getContractAt(TestERC721.abi, TestERC721.address, signers[3]) as TestERC721;

    appUser = new ethers.Contract(swapKiwi.address, SwapKiwi.abi, signers[2]) as SwapKiwi;
    otherAppUser = new ethers.Contract(swapKiwi.address, SwapKiwi.abi, signers[3]) as SwapKiwi;
    appUserAddress = await signers[2].getAddress();
    otherAppUserAddress = await signers[3].getAddress();
  });

  function getFilterName(eventName: string) {
    let filter: any;
    switch (eventName) {
      case "SwapExecuted":
        filter = swapKiwi.filters.SwapExecuted(null, null, null);
        break;
      case "SwapCanceled":
        filter = swapKiwi.filters.SwapCanceled(null, null);
        break;
      case "SwapProposed":
        filter = swapKiwi.filters.SwapProposed(null, null, null, null, null, null, null);
        break;
      case "SwapInitiated":
        filter = swapKiwi.filters.SwapInitiated(null, null, null, null, null, null, null);
      default: null
    }
    return filter;
  }

  async function getEventWithArgsFromLogs(txReceipt: TransactionReceipt, eventName: string): Promise<any | null> {
    if (txReceipt.logs) {
      const events = await swapKiwi.queryFilter(getFilterName(eventName), undefined);
      return events.map((e) => {
        if (e.event == eventName) {
          return {
            eventName: eventName,
            args: e.args
          }
        }
      }
      ).pop()
    }
    return null;
  }

  it("Should successfuly set app fee if caller is the owner", async function () {
    await swapKiwi.setAppFee(VALID_APP_FEE);
    expect((await swapKiwi.fee()).toString()).to.be.deep.equal(VALID_APP_FEE.toString());
  });

  it("Should fail to set app fee if caller is not owner", async function () {
    const nonOwnerContract = new ethers.Contract(SwapKiwi.address, SwapKiwi.abi, signers[6]) as SwapKiwi;

    await expect(nonOwnerContract.setAppFee(1000))
      .to.be.rejectedWith("Ownable: caller is not the owner");
  });

  it('Should fail to propose swap with invalid app fee', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      "SwapKiwi: Sent ETH amount needs to be more or equal application fee"
    );
  });

  it('Should fail to propose swap with different nft address and if length', async function () {
    await expect(appUser.proposeSwap(otherAppUserAddress, [], [13], [], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: NFT and ID arrays have to be same length"
    );
  });

  it('Should succesfully deposit NFT into escrow contract and emit "SwapProposed" event', async function () {
    await appUserNFT.mint(appUserAddress, 25);
    await appUserNFT.approve(swapKiwi.address, 25);
    expect(await appUserNFT.ownerOf(25)).to.be.deep.equal(appUserAddress);

    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [25], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");

    // check if all values are emitted in event
    expect(logs.eventName).to.be.deep.equal("SwapProposed");
    expect(logs.args.from).to.be.deep.equal(appUserAddress);
    expect(logs.args.to).to.be.deep.equal(otherAppUserAddress);
    expect(logs.args.nftAddresses[0]).to.be.deep.equal(appUserNFT.address);
    expect(logs.args.nftIds[0].toString()).to.be.deep.equal("25");
    expect(await appUserNFT.ownerOf(25)).to.be.deep.equal(swapKiwi.address);
  });

  it('Should succesfully cancel swap by first user (after swap proposed) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 140);
    await appUserNFT.approve(swapKiwi.address, 140);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [140], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(140)).to.be.deep.equal(appUserAddress);
  });

  it('Should succesfully cancel swap by second user (after swap proposed) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 141);
    await appUserNFT.approve(swapKiwi.address, 141);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [141], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(141)).to.be.deep.equal(appUserAddress);
  });

  it('Should succesfully cancel swap by first user (after swap initiated) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 120);
    await appUserNFT.approve(swapKiwi.address, 120);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [120], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 130);
    await otherAppUserNFT.mint(otherAppUserAddress, 131);
    await otherAppUserNFT.approve(swapKiwi.address, 130);
    await otherAppUserNFT.approve(swapKiwi.address, 131);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [130, 131],
      [0, 0],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserNFT.ownerOf(120)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(130)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(131)).to.be.deep.equal(otherAppUserAddress);
  });

  it('Should succesfully cancel swap by second user (after swap initiated) and emit "SwapCanceled" event', async function () {
    await appUserNFT.mint(appUserAddress, 121);
    await appUserNFT.approve(swapKiwi.address, 121);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [121], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 135);
    await otherAppUserNFT.mint(otherAppUserAddress, 136);
    await otherAppUserNFT.approve(swapKiwi.address, 135);
    await otherAppUserNFT.approve(swapKiwi.address, 136);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [135, 136],
      [0, 0],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(otherAppUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owners
    expect(await appUserNFT.ownerOf(121)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(135)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(136)).to.be.deep.equal(otherAppUserAddress);
  });

  it('Should succesfully cancel swap created with ether value', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 430);
    await appUserNFT.approve(swapKiwi.address, 430);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [430], [0], {
      value: VALID_APP_FEE.add(parseEther("20"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 431);
    await otherAppUserNFT.approve(swapKiwi.address, 431);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [431],
      [0],
      {
        value: VALID_APP_FEE.add(parseEther("10"))
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");

    const cancelTx = await otherAppUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    expect(await appUserNFT.ownerOf(430)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(431)).to.be.deep.equal(otherAppUserAddress);
    expect(firstUserBalance.sub(await appUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub(await otherAppUser.signer.getBalance()).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should fail to initiate swap if swap canceled', async function () {
    await appUserNFT.mint(appUserAddress, 170);
    await appUserNFT.approve(swapKiwi.address, 170);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [170], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    await cancelTx.wait(1);

    await otherAppUserNFT.mint(otherAppUserAddress, 301);
    await otherAppUserNFT.approve(swapKiwi.address, 301);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [301], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      `SwapKiwi: caller is not swap participator`
    );
  });

  it('Should fail to initiate swap with invalid app fee', async function () {
    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(parseEther("0.1"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [], [], [], {
      value: parseEther("0.01")
    })).to.be.rejectedWith(
      `SwapKiwi: Sent ETH amount needs to be more or equal application fee`
    );
  });

  it('Should fail to initiate swap twice', async function () {
    await appUserNFT.mint(appUserAddress, 189);
    await appUserNFT.approve(swapKiwi.address, 189);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [189], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUserNFT.mint(otherAppUserAddress, 302);
    await otherAppUserNFT.approve(swapKiwi.address, 302);
    await otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [302], [0], {
      value: VALID_APP_FEE
    })


    await otherAppUserNFT.mint(otherAppUserAddress, 303);
    await otherAppUserNFT.approve(swapKiwi.address, 303);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [303], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to initiate swap twice if proposed only with ether', async function () {
    await appUserNFT.mint(appUserAddress, 1732);
    await appUserNFT.approve(swapKiwi.address, 1732);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [1732], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());
    await otherAppUser.initiateSwap(swapIdFromLogs, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("0.25"))
    })


    await otherAppUserNFT.mint(otherAppUserAddress, 1733);
    await otherAppUserNFT.approve(swapKiwi.address, 1733);
    await expect(otherAppUser.initiateSwap(swapIdFromLogs, [otherAppUserNFT.address], [1733], [0], {
      value: VALID_APP_FEE
    })).to.be.rejectedWith(
      "SwapKiwi: swap already initiated"
    );
  });

  it('Should fail to cancel swap twice', async function () {
    await appUserNFT.mint(appUserAddress, 200);
    await appUserNFT.approve(swapKiwi.address, 200);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [200], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const cancelTx = await appUser.cancelSwap(swapIdFromLogs);
    const cancelTxReceipt = await cancelTx.wait(1);
    const cancelTxlogs = await getEventWithArgsFromLogs(cancelTxReceipt, "SwapCanceled");

    // check if all values are emitted in event
    expect(cancelTxlogs.eventName).to.be.deep.equal("SwapCanceled");
    expect(cancelTxlogs.args.canceledBy).to.be.deep.equal(appUserAddress);
    // expect that swap ID from "SwapCanceled" is same as swap ID from "swapProposed" event
    expect(cancelTxlogs.args.swapId.toString()).to.be.deep.equal(String(swapIdFromLogs));
    // check that NFT is returned to initial owner
    expect(await appUserNFT.ownerOf(200)).to.be.deep.equal(appUserAddress);

    await expect(appUser.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant"
    );
  });

  it("Should fail to cancel swap if user is not a swap participant", async function () {
    const nonSwapParticipant = new ethers.Contract(SwapKiwi.address, SwapKiwi.abi, signers[6]) as SwapKiwi;

    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 70);
    await appUserNFT.approve(swapKiwi.address, 70);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [70], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(nonSwapParticipant.cancelSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't cancel swap, must be swap participant");
  });

  it("Should fail to accept swap if second user didn't add NFTs or ether", async function () {
    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 2000);
    await appUserNFT.approve(swapKiwi.address, 2000);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [2000], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await expect(appUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: Can't accept swap, both participants didn't add NFTs");
  });

  it('Should fail to accept swap if not swap initiator', async function () {
    await appUserNFT.mint(appUserAddress, 2100);
    await appUserNFT.approve(swapKiwi.address, 2100);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [2100], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    await expect(otherAppUser.acceptSwap(swapIdFromLogs)).to.be.rejectedWith(
      "SwapKiwi: caller is not swap initiator"
    );
  });

  it('Should successfully execute NFT - NFT swap', async function () {
    // first user NFT minting and swap deposit into SwapKiwi
    await appUserNFT.mint(appUserAddress, 85);
    await appUserNFT.mint(appUserAddress, 86);
    await appUserNFT.approve(swapKiwi.address, 85);
    await appUserNFT.approve(swapKiwi.address, 86);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address, appUserNFT.address], [85, 86], [0, 0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    // check that first user NFTs are deposited into SwapKiwi
    expect(await appUserNFT.ownerOf(85)).to.be.deep.equal(swapKiwi.address);
    expect(await appUserNFT.ownerOf(86)).to.be.deep.equal(swapKiwi.address);

    // second user NFT minting and swap deposit into SwapKiwi
    await otherAppUserNFT.mint(otherAppUserAddress, 87);
    await otherAppUserNFT.mint(otherAppUserAddress, 88);
    await otherAppUserNFT.approve(swapKiwi.address, 87);
    await otherAppUserNFT.approve(swapKiwi.address, 88);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address, otherAppUserNFT.address],
      [87, 88],
      [0, 0],
      {
        value: VALID_APP_FEE
      }
    );
    const initiateSwapTxReceipt = await initiateSwapTx.wait(1);
    const initiateSwapLogs = await getEventWithArgsFromLogs(initiateSwapTxReceipt, "SwapInitiated");
    // check if all values are emitted in "SwapInitiated" event
    expect(initiateSwapLogs.eventName).to.be.deep.equal("SwapInitiated");
    expect(initiateSwapLogs.args.from).to.be.deep.equal(otherAppUserAddress);
    expect(initiateSwapLogs.args.to).to.be.deep.equal(appUserAddress);

    // check that second user NFTs are deposited into SwapKiwi
    expect(await otherAppUserNFT.ownerOf(87)).to.be.deep.equal(swapKiwi.address);
    expect(await otherAppUserNFT.ownerOf(88)).to.be.deep.equal(swapKiwi.address);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    const acceptSwapTxReceipt = await acceptSwapTx.wait(1);
    const acceptSwapLogs = await getEventWithArgsFromLogs(acceptSwapTxReceipt, "SwapExecuted");

    // check if all values are emitted in "SwapExecuted" event
    expect(acceptSwapLogs.eventName).to.be.deep.equal("SwapExecuted");
    expect(acceptSwapLogs.args.from).to.be.deep.equal(appUserAddress);
    expect(acceptSwapLogs.args.to).to.be.deep.equal(otherAppUserAddress);
    // check that NFTs are transfered from SwapKiwi to participants - same address because both have same signer

    expect(await otherAppUserNFT.ownerOf(85)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserNFT.ownerOf(86)).to.be.deep.equal(otherAppUserAddress);
    expect(await appUserNFT.ownerOf(87)).to.be.deep.equal(appUserAddress);
    expect(await appUserNFT.ownerOf(88)).to.be.deep.equal(appUserAddress);
  });

  it('Should successfully execute NFT + ether - NFT + ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();
    const secondUserBalance = await otherAppUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 375);
    await appUserNFT.approve(swapKiwi.address, 375);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [375], [0], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 376);
    await otherAppUserNFT.approve(swapKiwi.address, 376);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [376],
      [0],
      {
        value: VALID_APP_FEE.add(parseEther("25"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await appUserNFT.ownerOf(375)).to.be.deep.equal(otherAppUserAddress);
    expect(await otherAppUserNFT.ownerOf(376)).to.be.deep.equal(appUserAddress);
    expect(firstUserBalance.sub((await appUser.signer.getBalance()).add(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
    expect(secondUserBalance.sub((await otherAppUser.signer.getBalance()).sub(parseEther("25"))).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute ether - NFT swap', async function () {
    const secondUserBalance = await otherAppUser.signer.getBalance();

    const tx = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(parseEther("50"))
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    await otherAppUserNFT.mint(otherAppUserAddress, 1800);
    await otherAppUserNFT.approve(swapKiwi.address, 1800);
    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [otherAppUserNFT.address],
      [1800],
      [0],
      {
        value: VALID_APP_FEE
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await otherAppUserNFT.ownerOf(1800)).to.be.deep.equal(appUserAddress);
    expect(
      (
        await otherAppUser.signer.getBalance()
      ).sub(secondUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it('Should successfully execute NFT - ether swap', async function () {
    const firstUserBalance = await appUser.signer.getBalance();

    await appUserNFT.mint(appUserAddress, 1822);
    await appUserNFT.approve(swapKiwi.address, 1822);
    const tx = await appUser.proposeSwap(otherAppUserAddress, [appUserNFT.address], [1822], [0], {
      value: VALID_APP_FEE
    });
    const txReceipt = await tx.wait(1);
    const logs = await getEventWithArgsFromLogs(txReceipt, "SwapProposed");
    const swapIdFromLogs = Number(logs.args.swapId.toString());

    const initiateSwapTx = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("50"))
      }
    );
    await initiateSwapTx.wait(1);

    const acceptSwapTx = await appUser.acceptSwap(swapIdFromLogs);
    await acceptSwapTx.wait(1);

    expect(await appUserNFT.ownerOf(1822)).to.be.deep.equal(otherAppUserAddress);
    expect(
      (
        await appUser.signer.getBalance()
      ).sub(firstUserBalance).sub(parseEther("50")).lt(parseEther("1"))).to.be.equal(true);
  });

  it("Should successfully withdraw only collected fees", async function () {
    await swapKiwi.withdrawEther(await signers[7].getAddress());

    const tx1 = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt1 = await tx1.wait(1);
    const logs1 = await getEventWithArgsFromLogs(txReceipt1, "SwapProposed");
    const swapIdFromLogs1 = Number(logs1.args.swapId.toString());
    const initiateSwapTx1 = await otherAppUser.initiateSwap(
      swapIdFromLogs1,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx1.wait(1);
    const acceptSwapTx1 = await appUser.acceptSwap(swapIdFromLogs1);
    await acceptSwapTx1.wait(1);
    const tx2 = await appUser.proposeSwap(otherAppUserAddress, [], [], [], {
      value: VALID_APP_FEE.add(ethers.utils.parseEther("1"))
    });
    const txReceipt2 = await tx2.wait(1);
    const logs2 = await getEventWithArgsFromLogs(txReceipt2, "SwapProposed");
    const swapIdFromLogs = Number(logs2.args.swapId.toString());
    const initiateSwapTx2 = await otherAppUser.initiateSwap(
      swapIdFromLogs,
      [],
      [],
      [],
      {
        value: VALID_APP_FEE.add(parseEther("5"))
      }
    );
    await initiateSwapTx2.wait(1);

    await swapKiwi.withdrawEther(appUserNFT.address)

    expect((await ethers.provider.getBalance(appUserNFT.address)).toString())
      .to.be.deep.equal(VALID_APP_FEE.mul(4).toString())
  });

  it("Should fail to withdraw collected fees if not owner", async function () {
    await expect(appUser.withdrawEther(appUser.address))
      .to.be.rejectedWith(
        "Ownable: caller is not the owner");
  });

  it("Should fail to withdraw collected fees if sent to zero address", async function () {
    await expect(swapKiwi.withdrawEther("0x0000000000000000000000000000000000000000"))
      .to.be.rejectedWith("SwapKiwi: transfer to the zero address");
  });
});
Example #6
Source File: AmmSpec2.ts    From perpetual-protocol with GNU General Public License v3.0 5 votes vote down vote up
describe("Amm Unit Test 2 (Waffle)", async () => {
    const [wallet1, wallet2] = new MockProvider().getWallets()
    let amm: Amm
    let l2PriceFeed: MockContract
    let quoteToken: MockContract
    let clearingHouse: MockContract

    const AmmArtifact = await artifacts.readArtifact(ContractFullyQualifiedName.Amm)
    const IERC20Artifact = await artifacts.readArtifact(ContractFullyQualifiedName.IERC20)
    const L2PriceFeedArtifact = await artifacts.readArtifact(ContractFullyQualifiedName.L2PriceFeed)

    beforeEach(async () => {
        quoteToken = await deployMockContract(wallet1, IERC20Artifact.abi)
        clearingHouse = await deployMockContract(wallet1, [])
        l2PriceFeed = await deployMockContract(wallet1, L2PriceFeedArtifact.abi)
        amm = ((await deployContract(wallet1, AmmArtifact, [], { gasLimit: 6000000 })) as unknown) as Amm
        await amm.initialize(
            parseEther("1000"),
            parseEther("100"),
            parseEther("0.9"), // tradeLimitRatio
            parseEther("3600"), // fundingPeriod - 1hr
            l2PriceFeed.address,
            utils.formatBytes32String("ETH"),
            quoteToken.address,
            BigNumber.from(0), // fluctuation
            BigNumber.from(0), // toll
            BigNumber.from(0), // spread
        )
        await amm.setCounterParty(clearingHouse.address)
        amm.connect(clearingHouse.address)
    })

    describe("price", () => {
        it("getUnderlyingPrice", async () => {
            const price = parseEther("1")
            const priceFeedKeyBytes32 = await amm.priceFeedKey()
            const priceFeedKeyStr = utils.parseBytes32String(priceFeedKeyBytes32)
            expect(priceFeedKeyStr).eq("ETH")
            await l2PriceFeed.mock.getPrice.withArgs(priceFeedKeyBytes32).returns(price)
            expect((await amm.getUnderlyingPrice()).d).deep.eq(price)
        })
    })

    describe("setCap", () => {
        it("change maxHoldingBaseAsset and openInterestNotionalCap", async () => {
            await expect(amm.setCap({ d: 100 }, { d: 200 }))
                .to.emit(amm, "CapChanged")
                .withArgs("100", "200")
            expect((await amm.getMaxHoldingBaseAsset()).d).deep.eq(BigNumber.from(100))
            expect((await amm.getOpenInterestNotionalCap()).d).deep.eq(BigNumber.from(200))
        })
    })

    describe("setPriceFeed", () => {
        it("set priceFeed correctly", async () => {
            const updatedPriceFeed = "0x77F9710E7d0A19669A13c055F62cd80d313dF022"
            expect(await amm.priceFeed()).to.eq(l2PriceFeed.address)
            await expect(amm.setPriceFeed(updatedPriceFeed))
                .to.emit(amm, "PriceFeedUpdated")
                .withArgs(updatedPriceFeed)
            expect(await amm.priceFeed()).to.eq(updatedPriceFeed)
        })

        it("set priceFeed via non-owner causes revert transaction", async () => {
            await expect(amm.connect(wallet2).setPriceFeed(l2PriceFeed.address)).to.be.revertedWith(
                "PerpFiOwnableUpgrade: caller is not the owner",
            )
        })

        it("revert if priceFeed address is zero", async () => {
            await expect(amm.setPriceFeed(constants.AddressZero)).to.be.revertedWith("invalid PriceFeed address")
        })
    })
})