|
|
|
@ -6,6 +6,8 @@ import {
|
|
|
|
|
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
|
|
|
|
import { expect } from "chai";
|
|
|
|
|
import {
|
|
|
|
|
BigNumber,
|
|
|
|
|
BytesLike,
|
|
|
|
|
ContractReceipt,
|
|
|
|
|
ContractTransaction,
|
|
|
|
|
Wallet,
|
|
|
|
@ -36,10 +38,6 @@ import {
|
|
|
|
|
p2pixFixture,
|
|
|
|
|
randomSigners,
|
|
|
|
|
} from "./utils/fixtures";
|
|
|
|
|
import {
|
|
|
|
|
parseEther,
|
|
|
|
|
stringToHex,
|
|
|
|
|
} from "viem";
|
|
|
|
|
|
|
|
|
|
describe("P2PIX", () => {
|
|
|
|
|
type WalletWithAddress = Wallet & SignerWithAddress;
|
|
|
|
@ -62,10 +60,11 @@ describe("P2PIX", () => {
|
|
|
|
|
let merkleRoot: string; // MerkleRoot from seller's allowlist
|
|
|
|
|
let proof: string[]; // Owner's proof as whitelisted address
|
|
|
|
|
|
|
|
|
|
const fundAmount: BigInt = parseEther("10000");
|
|
|
|
|
const price: BigInt = parseEther("100");
|
|
|
|
|
const fundAmount: BigNumber =
|
|
|
|
|
ethers.utils.parseEther("10000");
|
|
|
|
|
const price: BigNumber = ethers.utils.parseEther("100");
|
|
|
|
|
|
|
|
|
|
const zero = '0x0000000000000000000000000000000000000000';
|
|
|
|
|
const zero = ethers.constants.AddressZero;
|
|
|
|
|
|
|
|
|
|
before("Set signers and reset network", async () => {
|
|
|
|
|
[owner, acc01, acc02, acc03] =
|
|
|
|
@ -172,7 +171,7 @@ describe("P2PIX", () => {
|
|
|
|
|
await expect(p2pix.withdrawBalance())
|
|
|
|
|
.to.changeEtherBalances(
|
|
|
|
|
[owner.address, p2pix.address],
|
|
|
|
|
[price, price * -1n],
|
|
|
|
|
[price, price.mul(-1)],
|
|
|
|
|
)
|
|
|
|
|
.and.to.emit(p2pix, "FundsWithdrawn")
|
|
|
|
|
.withArgs(owner.address, price);
|
|
|
|
@ -338,7 +337,7 @@ describe("P2PIX", () => {
|
|
|
|
|
const root = ethers.utils.keccak256(
|
|
|
|
|
ethers.utils.toUtf8Bytes("root"),
|
|
|
|
|
);
|
|
|
|
|
const tx = p2pix.deposit(pTarget, root, erc20.address, parseEther("100000001"), true);
|
|
|
|
|
const tx = p2pix.deposit(pTarget, root, erc20.address, ethers.utils.parseEther("100000001"), true);
|
|
|
|
|
|
|
|
|
|
await expect(tx).to.be.revertedWithCustomError(
|
|
|
|
|
p2pix,
|
|
|
|
@ -385,10 +384,10 @@ describe("P2PIX", () => {
|
|
|
|
|
await expect(tx).to.changeTokenBalances(
|
|
|
|
|
erc20,
|
|
|
|
|
[owner.address, p2pix.address],
|
|
|
|
|
[price * -1n, price],
|
|
|
|
|
[price.mul(-1), price],
|
|
|
|
|
);
|
|
|
|
|
expect(storage).to.eq(price);
|
|
|
|
|
expect(pixTarget).to.eq(stringToHex(pTarget,{size:32}));
|
|
|
|
|
expect(pixTarget).to.eq(await p2pix.callStatic.getStr(pTarget));
|
|
|
|
|
expect(valid).to.eq(true);
|
|
|
|
|
expect(allowList).to.eq(root);
|
|
|
|
|
expect(balances[0]).to.eq(price);
|
|
|
|
@ -416,10 +415,10 @@ describe("P2PIX", () => {
|
|
|
|
|
ethers.utils.toUtf8Bytes("root"),
|
|
|
|
|
);
|
|
|
|
|
const nullRoot = ethers.constants.HashZero;
|
|
|
|
|
const price2 = price * 2n;
|
|
|
|
|
const price3 = price * 3n;
|
|
|
|
|
const price4 = price * 4n;
|
|
|
|
|
const prices: BigInt[] = [
|
|
|
|
|
const price2 = price.mul(ethers.BigNumber.from(2));
|
|
|
|
|
const price3 = price.mul(ethers.BigNumber.from(3));
|
|
|
|
|
const price4 = price.mul(ethers.BigNumber.from(4));
|
|
|
|
|
const prices: BigNumber[] = [
|
|
|
|
|
price,
|
|
|
|
|
price2,
|
|
|
|
|
price3,
|
|
|
|
@ -565,7 +564,7 @@ describe("P2PIX", () => {
|
|
|
|
|
const tx = transactions[i];
|
|
|
|
|
const addr = addresses[i];
|
|
|
|
|
const depositPrice = depositPrices[i];
|
|
|
|
|
const amount = parseEther("100") * BigInt(i+1) * -1n;
|
|
|
|
|
const amount = ethers.utils.parseEther("100").mul(i+1).mul(-1).toBigInt();
|
|
|
|
|
|
|
|
|
|
await expect(tx)
|
|
|
|
|
.to.emit(p2pix, "DepositAdded")
|
|
|
|
@ -583,22 +582,22 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(prices[3]).to.eq(balances[3]);
|
|
|
|
|
|
|
|
|
|
expect(storage1).to.eq(price);
|
|
|
|
|
expect(pixTarget1).to.eq(stringToHex(pTarget,{size:32}));
|
|
|
|
|
expect(pixTarget1).to.eq(await p2pix.callStatic.getStr(pTarget));
|
|
|
|
|
expect(valid1).to.eq(true);
|
|
|
|
|
expect(allowList1).to.eq(root);
|
|
|
|
|
|
|
|
|
|
expect(storage2).to.eq(price2);
|
|
|
|
|
expect(pixTarget2).to.eq(stringToHex(pTarget2,{size:32}));
|
|
|
|
|
expect(pixTarget2).to.eq(await p2pix.callStatic.getStr(pTarget2));
|
|
|
|
|
expect(valid2).to.eq(false);
|
|
|
|
|
expect(allowList2).to.eq(nullRoot);
|
|
|
|
|
|
|
|
|
|
expect(storage3).to.eq(price3);
|
|
|
|
|
expect(pixTarget3).to.eq(stringToHex(pTarget3,{size:32}));
|
|
|
|
|
expect(pixTarget3).to.eq(await p2pix.callStatic.getStr(pTarget3));
|
|
|
|
|
expect(valid3).to.eq(true);
|
|
|
|
|
expect(allowList3).to.eq(root);
|
|
|
|
|
|
|
|
|
|
expect(storage4).to.eq(price4);
|
|
|
|
|
expect(pixTarget4).to.eq(stringToHex(pTarget,{size:32}));
|
|
|
|
|
expect(pixTarget4).to.eq(await p2pix.callStatic.getStr(pTarget));
|
|
|
|
|
expect(valid4).to.eq(false);
|
|
|
|
|
expect(allowList4).to.eq(nullRoot);
|
|
|
|
|
});
|
|
|
|
@ -623,6 +622,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const fail2 = p2pix.lock(
|
|
|
|
|
zero,
|
|
|
|
@ -630,6 +630,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(fail).to.be.revertedWithCustomError(
|
|
|
|
@ -656,9 +657,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price * 2n,
|
|
|
|
|
price.mul(ethers.BigNumber.from(2)),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(fail).to.be.revertedWithCustomError(
|
|
|
|
@ -681,9 +683,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
1000n,
|
|
|
|
|
ethers.BigNumber.from(1000),
|
|
|
|
|
[ethers.utils.keccak256(ethers.utils.toUtf8Bytes("wrong"))],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(fail).to.be.revertedWithCustomError(
|
|
|
|
@ -694,13 +697,13 @@ describe("P2PIX", () => {
|
|
|
|
|
it("should revert if msg.sender does not have enough credit in his spend limit", async () => {
|
|
|
|
|
await erc20.approve(
|
|
|
|
|
p2pix.address,
|
|
|
|
|
price * 3n,
|
|
|
|
|
price.mul(3),
|
|
|
|
|
);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
"1",
|
|
|
|
|
merkleRoot,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price * 3n,
|
|
|
|
|
price.mul(3),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
const fail = p2pix
|
|
|
|
@ -708,9 +711,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price * 2n,
|
|
|
|
|
price.mul(2),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(fail).to.be.revertedWithCustomError(
|
|
|
|
@ -718,6 +722,42 @@ describe("P2PIX", () => {
|
|
|
|
|
P2PixErrors.AmountNotAllowed,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should override spend limit if buyer pays the bond", async () => {
|
|
|
|
|
await erc20.approve(
|
|
|
|
|
p2pix.address,
|
|
|
|
|
price.mul(3),
|
|
|
|
|
);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
"1",
|
|
|
|
|
merkleRoot,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price.mul(3),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
await erc20
|
|
|
|
|
.transfer(
|
|
|
|
|
acc02.address,
|
|
|
|
|
price,
|
|
|
|
|
);
|
|
|
|
|
await erc20
|
|
|
|
|
.connect(acc02)
|
|
|
|
|
.approve(
|
|
|
|
|
p2pix.address,
|
|
|
|
|
price.mul(30000),
|
|
|
|
|
);
|
|
|
|
|
const bond = p2pix
|
|
|
|
|
.connect(acc02)
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price.mul(2),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(bond).to.be.ok;
|
|
|
|
|
});
|
|
|
|
|
it("should create a lock, update storage and emit events via the allowlist path", async () => {
|
|
|
|
|
const target = "333";
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
@ -736,6 +776,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
proof,
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
1,
|
|
|
|
@ -757,7 +798,7 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(storage.counter).to.eq(1);
|
|
|
|
|
expect(storage.amount).to.eq(price);
|
|
|
|
|
expect(storage.expirationBlock).to.eq(expiration);
|
|
|
|
|
expect(storage.pixTarget).to.eq(stringToHex(target,{size:32}));
|
|
|
|
|
expect(storage.pixTarget).to.eq(await p2pix.callStatic.getStr(target));
|
|
|
|
|
expect(storage.buyerAddress).to.eq(acc01.address);
|
|
|
|
|
expect(storage.token).to.eq(erc20.address);
|
|
|
|
|
});
|
|
|
|
@ -780,6 +821,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
1,
|
|
|
|
@ -800,7 +842,7 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(storage.counter).to.eq(1);
|
|
|
|
|
expect(storage.amount).to.eq(price);
|
|
|
|
|
expect(storage.expirationBlock).to.eq(expiration);
|
|
|
|
|
expect(storage.pixTarget).to.eq(stringToHex(target,{size:32}));
|
|
|
|
|
expect(storage.pixTarget).to.eq(await p2pix.callStatic.getStr(target));
|
|
|
|
|
expect(storage.buyerAddress).to.eq(acc01.address);
|
|
|
|
|
expect(storage.token).to.eq(erc20.address);
|
|
|
|
|
|
|
|
|
@ -810,12 +852,14 @@ describe("P2PIX", () => {
|
|
|
|
|
});
|
|
|
|
|
it("should create a lock, update storage and emit events via the reputation path 2", async () => {
|
|
|
|
|
const root = ethers.constants.HashZero;
|
|
|
|
|
const newPrice = price * 2n + 1n;
|
|
|
|
|
const newPrice = price
|
|
|
|
|
.mul(ethers.constants.Two)
|
|
|
|
|
.add(ethers.constants.One);
|
|
|
|
|
const endtoendID = ethers.constants.HashZero;
|
|
|
|
|
const target = "101";
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(target, { size: 32 }), price, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(target), price, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
const messageHashBytes =
|
|
|
|
|
ethers.utils.arrayify(messageToSign);
|
|
|
|
@ -839,6 +883,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
await p2pix
|
|
|
|
|
.connect(acc01)
|
|
|
|
@ -852,9 +897,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price + 1n,
|
|
|
|
|
price.add(ethers.constants.One),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
2,
|
|
|
|
@ -874,10 +920,10 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(storage.seller).to.eq(owner.address);
|
|
|
|
|
expect(storage.counter).to.eq(2);
|
|
|
|
|
expect(storage.amount).to.eq(
|
|
|
|
|
price+1n,
|
|
|
|
|
price.add(ethers.constants.One),
|
|
|
|
|
);
|
|
|
|
|
expect(storage.expirationBlock).to.eq(expiration);
|
|
|
|
|
expect(storage.pixTarget).to.eq(stringToHex(target,{size:32}));
|
|
|
|
|
expect(storage.pixTarget).to.eq(await p2pix.callStatic.getStr(target));
|
|
|
|
|
expect(storage.buyerAddress).to.eq(acc01.address);
|
|
|
|
|
expect(storage.token).to.eq(erc20.address);
|
|
|
|
|
|
|
|
|
@ -887,8 +933,8 @@ describe("P2PIX", () => {
|
|
|
|
|
});
|
|
|
|
|
// edge case test
|
|
|
|
|
it("should create multiple locks", async () => {
|
|
|
|
|
const newPrice = price / 2n;
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const newPrice = price.div(ethers.BigNumber.from(2));
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
target,
|
|
|
|
@ -905,6 +951,7 @@ describe("P2PIX", () => {
|
|
|
|
|
newPrice,
|
|
|
|
|
proof,
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage1: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
1,
|
|
|
|
@ -918,9 +965,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage2: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
2,
|
|
|
|
@ -934,9 +982,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const storage3: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
3,
|
|
|
|
@ -955,24 +1004,24 @@ describe("P2PIX", () => {
|
|
|
|
|
// const lockStatus4 = await p2pix.callStatic.getLocksStatus([]);
|
|
|
|
|
|
|
|
|
|
// All getLocksStatus calls were batched via the Multicall contract.
|
|
|
|
|
const ls1: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls1: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
getBnFrom([1, 7, 7, 2, 3, 4, 5, 5, 2, 3]),
|
|
|
|
|
getBnFrom([1, 0, 0, 1, 1, 0, 0, 0, 1, 1]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const ls2: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls2: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
getBnFrom([0, 1, 2, 3]),
|
|
|
|
|
getBnFrom([0, 1, 1, 1]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const ls3: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls3: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
getBnFrom([7, 7, 333, 14, 777]),
|
|
|
|
|
getBnFrom([0, 0, 0, 0, 0]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const ls4 = [[], []];
|
|
|
|
|
|
|
|
|
|
const batchedLocks: Array<BigInt[]> = [
|
|
|
|
|
const batchedLocks: Array<BigNumber[]> = [
|
|
|
|
|
ls1,
|
|
|
|
|
ls2,
|
|
|
|
|
ls3,
|
|
|
|
@ -989,7 +1038,7 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
const blockNumber = batchCall[0];
|
|
|
|
|
|
|
|
|
|
const result: Array<Bytes> = batchCall[1].slice(
|
|
|
|
|
const result: Array<BytesLike> = batchCall[1].slice(
|
|
|
|
|
0,
|
|
|
|
|
4,
|
|
|
|
|
);
|
|
|
|
@ -1023,7 +1072,7 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(storage3.counter).to.eq(3);
|
|
|
|
|
|
|
|
|
|
expect(storage1.amount).to.eq(newPrice);
|
|
|
|
|
expect(BigInt(100))
|
|
|
|
|
expect(ethers.BigNumber.from(100))
|
|
|
|
|
.to.eq(storage2.amount)
|
|
|
|
|
.and.to.eq(storage3.amount);
|
|
|
|
|
|
|
|
|
@ -1031,7 +1080,7 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(storage2.expirationBlock).to.eq(expiration2);
|
|
|
|
|
expect(storage3.expirationBlock).to.eq(expiration3);
|
|
|
|
|
|
|
|
|
|
expect(stringToHex(target,{size:32}))
|
|
|
|
|
expect(await p2pix.callStatic.getStr(target))
|
|
|
|
|
.to.eq(storage1.pixTarget)
|
|
|
|
|
.and.to.eq(storage2.pixTarget)
|
|
|
|
|
.and.to.eq(storage3.pixTarget);
|
|
|
|
@ -1069,7 +1118,7 @@ describe("P2PIX", () => {
|
|
|
|
|
it("should setValidState, update storage and emit events", async () => {
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
BigInt(10101).toString(),
|
|
|
|
|
ethers.BigNumber.from(10101).toString(),
|
|
|
|
|
merkleRoot,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price,
|
|
|
|
@ -1098,7 +1147,7 @@ describe("P2PIX", () => {
|
|
|
|
|
it("should cancel multiple balances", async () => {
|
|
|
|
|
const hashZero = ethers.constants.HashZero;
|
|
|
|
|
await erc20.mint([acc01.address, acc02.address], price);
|
|
|
|
|
const target = BigInt(1).toString();
|
|
|
|
|
const target = ethers.BigNumber.from("1").toString();
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
target,
|
|
|
|
@ -1188,7 +1237,7 @@ describe("P2PIX", () => {
|
|
|
|
|
});
|
|
|
|
|
describe("Release", async () => {
|
|
|
|
|
it("should revert if lock has expired", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["uint160", "uint80", "bytes32"],
|
|
|
|
|
[target, 100, ethers.constants.HashZero],
|
|
|
|
@ -1210,9 +1259,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
await mine(13);
|
|
|
|
@ -1228,11 +1278,11 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should revert if lock has already been released", async () => {
|
|
|
|
|
const target = BigInt(1).toString();
|
|
|
|
|
const target = ethers.BigNumber.from("1").toString();
|
|
|
|
|
const hashZero = ethers.constants.HashZero;
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(target,{size:32}), 100, hashZero],
|
|
|
|
|
[await p2pix.callStatic.getStr(target), 100, hashZero],
|
|
|
|
|
);
|
|
|
|
|
const flatSig = await acc01.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign),
|
|
|
|
@ -1251,9 +1301,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
await p2pix.release(
|
|
|
|
@ -1273,10 +1324,10 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should revert if signed message has already been used", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(target,{size:32}), 100, ethers.constants.HashZero],
|
|
|
|
|
[await p2pix.callStatic.getStr(target), 100, ethers.constants.HashZero],
|
|
|
|
|
);
|
|
|
|
|
const flatSig = await owner.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign),
|
|
|
|
@ -1295,9 +1346,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await p2pix
|
|
|
|
@ -1312,9 +1364,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const fail = p2pix
|
|
|
|
|
.connect(acc01)
|
|
|
|
@ -1330,10 +1383,10 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should revert if ecrecovered signer is invalid", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(target,{size:32}), 100, ethers.constants.HashZero],
|
|
|
|
|
[await p2pix.callStatic.getStr(target), 100, ethers.constants.HashZero],
|
|
|
|
|
);
|
|
|
|
|
const flatSig = await acc03.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign),
|
|
|
|
@ -1353,9 +1406,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const fail = p2pix
|
|
|
|
|
.connect(acc01)
|
|
|
|
@ -1373,10 +1427,10 @@ describe("P2PIX", () => {
|
|
|
|
|
it("should release lock, update storage and emit events", async () => {
|
|
|
|
|
const zero = ethers.constants.Zero;
|
|
|
|
|
const endtoendID = ethers.constants.HashZero;
|
|
|
|
|
const pixTarget = BigInt(101).toString();
|
|
|
|
|
const pixTarget = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(pixTarget,{size:32}), 100, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(pixTarget), 100, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
// Note: messageToSign is a string, that is 66-bytes long, to sign the
|
|
|
|
|
// binary value, we must convert it to the 32 byte Array that
|
|
|
|
@ -1409,9 +1463,10 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const acc01Key = await p2pix.callStatic._castAddrToKey(
|
|
|
|
|
acc01.address,
|
|
|
|
@ -1438,7 +1493,7 @@ describe("P2PIX", () => {
|
|
|
|
|
|
|
|
|
|
const lockStatus1 =
|
|
|
|
|
await p2pix.callStatic.getLocksStatus([1]);
|
|
|
|
|
const ls1: [BigInt[], number[]] = [
|
|
|
|
|
const ls1: [BigNumber[], number[]] = [
|
|
|
|
|
[ethers.constants.One],
|
|
|
|
|
[3],
|
|
|
|
|
];
|
|
|
|
@ -1456,10 +1511,10 @@ describe("P2PIX", () => {
|
|
|
|
|
];
|
|
|
|
|
mtcCalls.push(cd2[0]);
|
|
|
|
|
const mtc2 = await multicall.callStatic.mtc2(mtcCalls);
|
|
|
|
|
const blockNumber: BigInt = mtc2[0];
|
|
|
|
|
const blockhash: Bytes = mtc2[1];
|
|
|
|
|
const blockNumber: BigNumber = mtc2[0];
|
|
|
|
|
const blockhash: BytesLike = mtc2[1];
|
|
|
|
|
const result = mtc2.slice(2).flat(1) as Result[];
|
|
|
|
|
const res1: Bytes[] = [result[1].returnData];
|
|
|
|
|
const res1: BytesLike[] = [result[1].returnData];
|
|
|
|
|
const decodedLockData = res1.map(r =>
|
|
|
|
|
ethers.utils.defaultAbiCoder.decode(
|
|
|
|
|
["uint256[]", "uint8[]"],
|
|
|
|
@ -1488,10 +1543,10 @@ describe("P2PIX", () => {
|
|
|
|
|
storage1.amount,
|
|
|
|
|
);
|
|
|
|
|
expect(storage1.expirationBlock).to.eq(
|
|
|
|
|
BigInt(17),
|
|
|
|
|
ethers.BigNumber.from(17),
|
|
|
|
|
);
|
|
|
|
|
expect(storage1.amount).to.eq(
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
);
|
|
|
|
|
expect(lockStatus1[0].toString()).to.equal(
|
|
|
|
|
ls1[0].toString(),
|
|
|
|
@ -1511,8 +1566,8 @@ describe("P2PIX", () => {
|
|
|
|
|
expect(used).to.eq(true);
|
|
|
|
|
expect(userRecordA).to.eq(zero);
|
|
|
|
|
expect(userRecord1).to.eq(zero);
|
|
|
|
|
expect(userRecordB).to.eq(BigInt(50));
|
|
|
|
|
expect(userRecord2).to.eq(BigInt(50));
|
|
|
|
|
expect(userRecordB).to.eq(ethers.BigNumber.from(50));
|
|
|
|
|
expect(userRecord2).to.eq(ethers.BigNumber.from(50));
|
|
|
|
|
await expect(tx).to.changeTokenBalances(
|
|
|
|
|
erc20,
|
|
|
|
|
[acc03.address, acc01.address, acc02.address ],
|
|
|
|
@ -1522,7 +1577,7 @@ describe("P2PIX", () => {
|
|
|
|
|
// edge case test
|
|
|
|
|
it("should release multiple locks", async () => {
|
|
|
|
|
const endtoendID = ethers.constants.HashZero;
|
|
|
|
|
const pixTarget = BigInt(101).toString();
|
|
|
|
|
const pixTarget = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const root = ethers.constants.HashZero;
|
|
|
|
|
const acc01Key = await p2pix.callStatic._castAddrToKey(
|
|
|
|
|
acc01.address,
|
|
|
|
@ -1538,7 +1593,7 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
const messageToSign1 = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(pixTarget,{size:32}), 100, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(pixTarget), 100, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
const flatSig1 = await owner.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign1),
|
|
|
|
@ -1546,7 +1601,7 @@ describe("P2PIX", () => {
|
|
|
|
|
// const sig1 = ethers.utils.splitSignature(flatSig1);
|
|
|
|
|
const messageToSign2 = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(pixTarget,{size:32}), 50, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(pixTarget), 50, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
const flatSig2 = await owner.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign2),
|
|
|
|
@ -1554,7 +1609,7 @@ describe("P2PIX", () => {
|
|
|
|
|
// const sig2 = ethers.utils.splitSignature(flatSig2);
|
|
|
|
|
const messageToSign3 = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(pixTarget,{size:32}), 25, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(pixTarget), 25, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
const flatSig3 = await owner.signMessage(
|
|
|
|
|
ethers.utils.arrayify(messageToSign3),
|
|
|
|
@ -1573,44 +1628,47 @@ describe("P2PIX", () => {
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
await p2pix
|
|
|
|
|
.connect(acc03)
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(50),
|
|
|
|
|
ethers.BigNumber.from(50),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
await p2pix
|
|
|
|
|
.connect(acc03)
|
|
|
|
|
.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(25),
|
|
|
|
|
ethers.BigNumber.from(25),
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const lockStatus1 =
|
|
|
|
|
await p2pix.callStatic.getLocksStatus([1, 2, 3, 44]);
|
|
|
|
|
const ls1: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls1: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
[
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
ethers.constants.Two,
|
|
|
|
|
BigInt(3),
|
|
|
|
|
BigInt(44),
|
|
|
|
|
ethers.BigNumber.from(3),
|
|
|
|
|
ethers.BigNumber.from(44),
|
|
|
|
|
],
|
|
|
|
|
getBnFrom([1, 1, 1, 0]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
const lockID2 = ethers.constants.Two;
|
|
|
|
|
const lockID3 = BigInt(3);
|
|
|
|
|
const lockID3 = ethers.BigNumber.from(3);
|
|
|
|
|
const storage1: Lock = await p2pix.callStatic.mapLocks(
|
|
|
|
|
lockID,
|
|
|
|
|
);
|
|
|
|
@ -1664,17 +1722,17 @@ describe("P2PIX", () => {
|
|
|
|
|
|
|
|
|
|
const lockStatus2 =
|
|
|
|
|
await p2pix.callStatic.getLocksStatus([1, 2, 3, 44]);
|
|
|
|
|
const ls2: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls2: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
[
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
ethers.constants.Two,
|
|
|
|
|
BigInt(3),
|
|
|
|
|
BigInt(44),
|
|
|
|
|
ethers.BigNumber.from(3),
|
|
|
|
|
ethers.BigNumber.from(44),
|
|
|
|
|
],
|
|
|
|
|
getBnFrom([3, 3, 3, 0]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const batchedLocks: Array<BigInt[]> = [
|
|
|
|
|
const batchedLocks: Array<BigNumber[]> = [
|
|
|
|
|
ls1.slice(0, 1)[0],
|
|
|
|
|
ls2.slice(0, 1)[0],
|
|
|
|
|
];
|
|
|
|
@ -1746,7 +1804,7 @@ describe("P2PIX", () => {
|
|
|
|
|
});
|
|
|
|
|
describe("Unexpire Locks", async () => {
|
|
|
|
|
it("should revert if lock isn't expired", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
target,
|
|
|
|
@ -1763,6 +1821,7 @@ describe("P2PIX", () => {
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
const fail = p2pix.unlockExpired([lockID]);
|
|
|
|
@ -1774,10 +1833,10 @@ describe("P2PIX", () => {
|
|
|
|
|
});
|
|
|
|
|
it("should revert if lock has already been released", async () => {
|
|
|
|
|
const endtoendID = ethers.constants.HashZero;
|
|
|
|
|
const pixTarget = BigInt(101).toString();
|
|
|
|
|
const pixTarget = ethers.BigNumber.from(101).toString();
|
|
|
|
|
const messageToSign = ethers.utils.solidityKeccak256(
|
|
|
|
|
["bytes32", "uint80", "bytes32"],
|
|
|
|
|
[stringToHex(pixTarget,{size:32}), 1, endtoendID],
|
|
|
|
|
[await p2pix.callStatic.getStr(pixTarget), 1, endtoendID],
|
|
|
|
|
);
|
|
|
|
|
const messageHashBytes =
|
|
|
|
|
ethers.utils.arrayify(messageToSign);
|
|
|
|
@ -1801,6 +1860,7 @@ describe("P2PIX", () => {
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
// await mine(10);
|
|
|
|
@ -1817,7 +1877,7 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should unlock expired locks, update storage and emit events", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
target,
|
|
|
|
@ -1834,17 +1894,18 @@ describe("P2PIX", () => {
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
[],
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
await mine(11);
|
|
|
|
|
|
|
|
|
|
const lockStatus1 =
|
|
|
|
|
await p2pix.callStatic.getLocksStatus([11, 1, 777]);
|
|
|
|
|
const ls1: [BigInt[], BigInt[]] = [
|
|
|
|
|
const ls1: [BigNumber[], BigNumber[]] = [
|
|
|
|
|
[
|
|
|
|
|
BigInt(11),
|
|
|
|
|
ethers.BigNumber.from(11),
|
|
|
|
|
ethers.constants.One,
|
|
|
|
|
BigInt(777),
|
|
|
|
|
ethers.BigNumber.from(777),
|
|
|
|
|
],
|
|
|
|
|
getBnFrom([0, 2, 0]),
|
|
|
|
|
];
|
|
|
|
@ -1879,7 +1940,7 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should unlock expired through lock function", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
// test method through lock fx
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
@ -1897,6 +1958,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
proof,
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
// as return values of non view functions can't be accessed
|
|
|
|
|
// outside the evm, we fetch the lockID from the emitted event.
|
|
|
|
@ -1933,9 +1995,10 @@ describe("P2PIX", () => {
|
|
|
|
|
const tx1 = await p2pix.lock(
|
|
|
|
|
owner.address,
|
|
|
|
|
erc20.address,
|
|
|
|
|
BigInt(100),
|
|
|
|
|
ethers.BigNumber.from(100),
|
|
|
|
|
[],
|
|
|
|
|
[lockID],
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
const remaining = await p2pix.callStatic.getBalance(
|
|
|
|
|
owner.address,
|
|
|
|
@ -1947,7 +2010,7 @@ describe("P2PIX", () => {
|
|
|
|
|
.to.emit(p2pix, "LockReturned")
|
|
|
|
|
.withArgs(acc01.address, lockID);
|
|
|
|
|
expect(remaining).to.eq(
|
|
|
|
|
price - 100n,
|
|
|
|
|
price.sub(ethers.BigNumber.from(100)),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should unlock expired through withdraw function", async () => {
|
|
|
|
@ -1969,6 +2032,7 @@ describe("P2PIX", () => {
|
|
|
|
|
price,
|
|
|
|
|
proof,
|
|
|
|
|
[],
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
const lockID = ethers.constants.One;
|
|
|
|
|
// mine blocks to expire lock
|
|
|
|
@ -1991,7 +2055,7 @@ describe("P2PIX", () => {
|
|
|
|
|
|
|
|
|
|
describe("Seller Withdraw", async () => {
|
|
|
|
|
it("should revert if the wished amount is invalid", async () => {
|
|
|
|
|
const target = BigInt(101).toString();
|
|
|
|
|
const target = ethers.BigNumber.from(101).toString();
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
await p2pix.deposit(
|
|
|
|
|
target,
|
|
|
|
@ -2004,7 +2068,7 @@ describe("P2PIX", () => {
|
|
|
|
|
.connect(acc02)
|
|
|
|
|
.withdraw(
|
|
|
|
|
erc20.address,
|
|
|
|
|
price * 2n,
|
|
|
|
|
price.mul(ethers.constants.Two),
|
|
|
|
|
[],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
@ -2014,10 +2078,10 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
it("should withdraw remaining funds from deposit, update storage and emit event", async () => {
|
|
|
|
|
const newPrice = price / 2n;
|
|
|
|
|
const newPrice = price.div(ethers.constants.Two);
|
|
|
|
|
await erc20.approve(p2pix.address, price);
|
|
|
|
|
const dep = await p2pix.deposit(
|
|
|
|
|
BigInt(101).toString(),
|
|
|
|
|
ethers.BigNumber.from(101).toString(),
|
|
|
|
|
merkleRoot,
|
|
|
|
|
erc20.address,
|
|
|
|
|
price,
|
|
|
|
@ -2025,7 +2089,7 @@ describe("P2PIX", () => {
|
|
|
|
|
);
|
|
|
|
|
const tx = await p2pix.withdraw(
|
|
|
|
|
erc20.address,
|
|
|
|
|
price / 2n,
|
|
|
|
|
price.div(ethers.constants.Two),
|
|
|
|
|
[],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
@ -2034,7 +2098,7 @@ describe("P2PIX", () => {
|
|
|
|
|
.to.changeTokenBalance(
|
|
|
|
|
erc20,
|
|
|
|
|
owner.address,
|
|
|
|
|
price * -1n,
|
|
|
|
|
price.mul(-1),
|
|
|
|
|
)
|
|
|
|
|
.and.to.changeTokenBalance(
|
|
|
|
|
erc20,
|
|
|
|
@ -2046,7 +2110,7 @@ describe("P2PIX", () => {
|
|
|
|
|
.and.to.changeTokenBalance(
|
|
|
|
|
erc20,
|
|
|
|
|
p2pix.address,
|
|
|
|
|
(price/2n) * -1n,
|
|
|
|
|
price.div(ethers.constants.Two).mul(-1),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(tx)
|
|
|
|
|