feat: deployment scripts fixed and lock fx unit tests added
This commit is contained in:
parent
1a4b4973d4
commit
d541e7b70c
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/ce60783a904758b510bc61bc47947601.json"
|
"buildInfo": "../../build-info/4a0f142c7439e90ed9431fa5c0d6c0c6.json"
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,25 @@
|
|||||||
"name": "ReputationUpdated",
|
"name": "ReputationUpdated",
|
||||||
"type": "event"
|
"type": "event"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "seller",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "merkleRoot",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RootUpdated",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"anonymous": false,
|
"anonymous": false,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/351fea96dbbd5ddc7250e49d27b4151f.json"
|
"buildInfo": "../../build-info/4a0f142c7439e90ed9431fa5c0d6c0c6.json"
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity 0.8.9;
|
pragma solidity 0.8.9;
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
interface EventAndErrors {
|
interface EventAndErrors {
|
||||||
/// ███ Events ████████████████████████████████████████████████████████████
|
/// ███ Events ████████████████████████████████████████████████████████████
|
||||||
|
|
||||||
@ -25,16 +26,29 @@ interface EventAndErrors {
|
|||||||
uint256 depositID,
|
uint256 depositID,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
);
|
);
|
||||||
event LockReleased(address indexed buyer, bytes32 lockId);
|
event LockReleased(
|
||||||
event LockReturned(address indexed buyer, bytes32 lockId);
|
address indexed buyer,
|
||||||
event FundsWithdrawn(address owner, uint256 amount);
|
bytes32 lockId
|
||||||
event ReputationUpdated(address reputation);
|
);
|
||||||
event LockBlocksUpdated(uint256 blocks);
|
event LockReturned(
|
||||||
event ValidSignersUpdated(address[] signers);
|
address indexed buyer,
|
||||||
|
bytes32 lockId
|
||||||
|
);
|
||||||
|
event FundsWithdrawn(
|
||||||
|
address owner,
|
||||||
|
uint256 amount
|
||||||
|
);
|
||||||
|
event RootUpdated(
|
||||||
|
address seller,
|
||||||
|
bytes32 merkleRoot
|
||||||
|
);
|
||||||
event AllowedERC20Updated(
|
event AllowedERC20Updated(
|
||||||
address indexed token,
|
address indexed token,
|
||||||
bool indexed state
|
bool indexed state
|
||||||
);
|
);
|
||||||
|
event ReputationUpdated(address reputation);
|
||||||
|
event LockBlocksUpdated(uint256 blocks);
|
||||||
|
event ValidSignersUpdated(address[] signers);
|
||||||
|
|
||||||
/// ███ Errors ████████████████████████████████████████████████████████████
|
/// ███ Errors ████████████████████████████████████████████████████████████
|
||||||
|
|
||||||
|
@ -194,40 +194,29 @@ contract P2PIX is
|
|||||||
msg.sender
|
msg.sender
|
||||||
);
|
);
|
||||||
|
|
||||||
mapLocks[lockID] = l;
|
_addLock(lockID, l, d);
|
||||||
d.remaining -= _amount;
|
|
||||||
|
|
||||||
emit LockAdded(
|
|
||||||
_buyerAddress,
|
|
||||||
lockID,
|
|
||||||
l.depositID,
|
|
||||||
_amount
|
|
||||||
);
|
|
||||||
|
|
||||||
// Halt execution and output `lockID`.
|
// Halt execution and output `lockID`.
|
||||||
return lockID;
|
return lockID;
|
||||||
} else {
|
} else {
|
||||||
uint256 userCredit = userRecord[
|
if (l.amount <= 1e2) {
|
||||||
_castAddrToKey(msg.sender)
|
_addLock(lockID, l, d);
|
||||||
];
|
// Halt execution and output `lockID`.
|
||||||
uint256 spendLimit;
|
return lockID;
|
||||||
(spendLimit) = _limiter(userCredit);
|
} else {
|
||||||
|
uint256 userCredit = userRecord[
|
||||||
|
_castAddrToKey(msg.sender)
|
||||||
|
];
|
||||||
|
uint256 spendLimit;
|
||||||
|
(spendLimit) = _limiter(userCredit);
|
||||||
|
|
||||||
if (l.amount > spendLimit || l.amount > 1e6)
|
if (l.amount > spendLimit || l.amount > 1e6)
|
||||||
revert AmountNotAllowed();
|
revert AmountNotAllowed();
|
||||||
|
|
||||||
mapLocks[lockID] = l;
|
_addLock(lockID, l, d);
|
||||||
d.remaining -= _amount;
|
// Halt execution and output `lockID`.
|
||||||
|
return lockID;
|
||||||
emit LockAdded(
|
}
|
||||||
_buyerAddress,
|
|
||||||
lockID,
|
|
||||||
l.depositID,
|
|
||||||
_amount
|
|
||||||
);
|
|
||||||
|
|
||||||
// Halt execution and output `lockID`.
|
|
||||||
return lockID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,6 +406,10 @@ contract P2PIX is
|
|||||||
sellerAllowList[
|
sellerAllowList[
|
||||||
_castAddrToKey(addr)
|
_castAddrToKey(addr)
|
||||||
] = merkleroot;
|
] = merkleroot;
|
||||||
|
emit RootUpdated(
|
||||||
|
addr,
|
||||||
|
merkleroot
|
||||||
|
);
|
||||||
} else revert OnlySeller();
|
} else revert OnlySeller();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,6 +580,22 @@ contract P2PIX is
|
|||||||
revert DepositAlreadyExists();
|
revert DepositAlreadyExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _addLock(
|
||||||
|
bytes32 _lockID,
|
||||||
|
DT.Lock memory _l,
|
||||||
|
DT.Deposit storage _d
|
||||||
|
) internal {
|
||||||
|
mapLocks[_lockID] = _l;
|
||||||
|
_d.remaining -= _l.amount;
|
||||||
|
|
||||||
|
emit LockAdded(
|
||||||
|
_l.buyerAddress,
|
||||||
|
_lockID,
|
||||||
|
_l.depositID,
|
||||||
|
_l.amount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// @notice Private view auxiliar logic that encodes/returns
|
/// @notice Private view auxiliar logic that encodes/returns
|
||||||
/// the `bytes32` identifier of an lock.
|
/// the `bytes32` identifier of an lock.
|
||||||
/// @dev reverts on a not expired lock with the same ID passed
|
/// @dev reverts on a not expired lock with the same ID passed
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||||
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||||
],
|
],
|
||||||
"p2pix": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee",
|
"p2pix": "0x37c856F4d5bC2597da60f607b1335738468453F3",
|
||||||
"token": "0x5BdEa33E2D14E3D4C66f9A7bbbc38Cd785D0C592"
|
"token": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee"
|
||||||
}
|
}
|
@ -14,8 +14,8 @@
|
|||||||
"compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile",
|
"compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile",
|
||||||
"typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain",
|
"typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain",
|
||||||
"test": "hardhat test",
|
"test": "hardhat test",
|
||||||
"deploy1:localhost": "hardhat run scripts/1-deploy-p2pix.ts --network localhost",
|
"deploy1:localhost": "hardhat run scripts/1-deploy-mockToken.ts --network localhost",
|
||||||
"deploy2:localhost": "hardhat run scripts/2-deploy-mockToken.ts --network localhost",
|
"deploy2:localhost": "hardhat run scripts/2-deploy-p2pix.ts --network localhost",
|
||||||
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && yarn typechain",
|
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && yarn typechain",
|
||||||
"lint": "yarn lint:sol && yarn lint:ts && yarn prettier:check",
|
"lint": "yarn lint:sol && yarn lint:ts && yarn prettier:check",
|
||||||
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
||||||
@ -49,6 +49,7 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
||||||
"@typescript-eslint/parser": "^5.42.0",
|
"@typescript-eslint/parser": "^5.42.0",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
|
"chalk": "4.x",
|
||||||
"commitizen": "^4.2.5",
|
"commitizen": "^4.2.5",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
|
@ -2,14 +2,8 @@ import "@nomiclabs/hardhat-ethers";
|
|||||||
import "@nomiclabs/hardhat-etherscan";
|
import "@nomiclabs/hardhat-etherscan";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { ethers, network } from "hardhat";
|
import { ethers, network } from "hardhat";
|
||||||
|
import { Deploys } from "../test/utils/fixtures";
|
||||||
|
|
||||||
// import hre from "hardhat";
|
|
||||||
|
|
||||||
interface Deploys {
|
|
||||||
signers: string[];
|
|
||||||
p2pix: string;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
let deploysJson: Deploys;
|
let deploysJson: Deploys;
|
||||||
|
|
||||||
@ -28,8 +22,18 @@ const main = async () => {
|
|||||||
const [deployer] = await ethers.getSigners();
|
const [deployer] = await ethers.getSigners();
|
||||||
console.log(`Deploying contracts with ${deployer.address}`);
|
console.log(`Deploying contracts with ${deployer.address}`);
|
||||||
|
|
||||||
|
const Reputation = await ethers.getContractFactory("Reputation");
|
||||||
|
const reputation = await Reputation.deploy();
|
||||||
|
await reputation.deployed();
|
||||||
|
|
||||||
const P2PIX = await ethers.getContractFactory("P2PIX");
|
const P2PIX = await ethers.getContractFactory("P2PIX");
|
||||||
const p2pix = await P2PIX.deploy(2, deploysJson.signers);
|
const p2pix = await P2PIX.deploy(
|
||||||
|
10,
|
||||||
|
deploysJson.signers,
|
||||||
|
reputation.address,
|
||||||
|
[deploysJson.token],
|
||||||
|
[true]
|
||||||
|
);
|
||||||
await p2pix.deployed();
|
await p2pix.deployed();
|
||||||
|
|
||||||
deploysJson.p2pix = p2pix.address;
|
deploysJson.p2pix = p2pix.address;
|
@ -26,6 +26,7 @@ export interface EventAndErrorsInterface extends utils.Interface {
|
|||||||
"LockReleased(address,bytes32)": EventFragment;
|
"LockReleased(address,bytes32)": EventFragment;
|
||||||
"LockReturned(address,bytes32)": EventFragment;
|
"LockReturned(address,bytes32)": EventFragment;
|
||||||
"ReputationUpdated(address)": EventFragment;
|
"ReputationUpdated(address)": EventFragment;
|
||||||
|
"RootUpdated(address,bytes32)": EventFragment;
|
||||||
"ValidSignersUpdated(address[])": EventFragment;
|
"ValidSignersUpdated(address[])": EventFragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ export interface EventAndErrorsInterface extends utils.Interface {
|
|||||||
getEvent(nameOrSignatureOrTopic: "LockReleased"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "LockReleased"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment;
|
||||||
|
getEvent(nameOrSignatureOrTopic: "RootUpdated"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +161,17 @@ export type ReputationUpdatedEvent = TypedEvent<
|
|||||||
export type ReputationUpdatedEventFilter =
|
export type ReputationUpdatedEventFilter =
|
||||||
TypedEventFilter<ReputationUpdatedEvent>;
|
TypedEventFilter<ReputationUpdatedEvent>;
|
||||||
|
|
||||||
|
export interface RootUpdatedEventObject {
|
||||||
|
seller: string;
|
||||||
|
merkleRoot: string;
|
||||||
|
}
|
||||||
|
export type RootUpdatedEvent = TypedEvent<
|
||||||
|
[string, string],
|
||||||
|
RootUpdatedEventObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type RootUpdatedEventFilter = TypedEventFilter<RootUpdatedEvent>;
|
||||||
|
|
||||||
export interface ValidSignersUpdatedEventObject {
|
export interface ValidSignersUpdatedEventObject {
|
||||||
signers: string[];
|
signers: string[];
|
||||||
}
|
}
|
||||||
@ -288,6 +301,12 @@ export interface EventAndErrors extends BaseContract {
|
|||||||
): ReputationUpdatedEventFilter;
|
): ReputationUpdatedEventFilter;
|
||||||
ReputationUpdated(reputation?: null): ReputationUpdatedEventFilter;
|
ReputationUpdated(reputation?: null): ReputationUpdatedEventFilter;
|
||||||
|
|
||||||
|
"RootUpdated(address,bytes32)"(
|
||||||
|
seller?: null,
|
||||||
|
merkleRoot?: null
|
||||||
|
): RootUpdatedEventFilter;
|
||||||
|
RootUpdated(seller?: null, merkleRoot?: null): RootUpdatedEventFilter;
|
||||||
|
|
||||||
"ValidSignersUpdated(address[])"(
|
"ValidSignersUpdated(address[])"(
|
||||||
signers?: null
|
signers?: null
|
||||||
): ValidSignersUpdatedEventFilter;
|
): ValidSignersUpdatedEventFilter;
|
||||||
|
@ -293,6 +293,25 @@ const _abi = [
|
|||||||
name: "ReputationUpdated",
|
name: "ReputationUpdated",
|
||||||
type: "event",
|
type: "event",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: false,
|
||||||
|
internalType: "address",
|
||||||
|
name: "seller",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: false,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "merkleRoot",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RootUpdated",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
anonymous: false,
|
anonymous: false,
|
||||||
inputs: [
|
inputs: [
|
||||||
|
File diff suppressed because one or more lines are too long
@ -276,6 +276,7 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
"LockReturned(address,bytes32)": EventFragment;
|
"LockReturned(address,bytes32)": EventFragment;
|
||||||
"OwnerUpdated(address,address)": EventFragment;
|
"OwnerUpdated(address,address)": EventFragment;
|
||||||
"ReputationUpdated(address)": EventFragment;
|
"ReputationUpdated(address)": EventFragment;
|
||||||
|
"RootUpdated(address,bytes32)": EventFragment;
|
||||||
"ValidSignersUpdated(address[])": EventFragment;
|
"ValidSignersUpdated(address[])": EventFragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -290,6 +291,7 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "OwnerUpdated"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "OwnerUpdated"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment;
|
||||||
|
getEvent(nameOrSignatureOrTopic: "RootUpdated"): EventFragment;
|
||||||
getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment;
|
getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,6 +423,17 @@ export type ReputationUpdatedEvent = TypedEvent<
|
|||||||
export type ReputationUpdatedEventFilter =
|
export type ReputationUpdatedEventFilter =
|
||||||
TypedEventFilter<ReputationUpdatedEvent>;
|
TypedEventFilter<ReputationUpdatedEvent>;
|
||||||
|
|
||||||
|
export interface RootUpdatedEventObject {
|
||||||
|
seller: string;
|
||||||
|
merkleRoot: string;
|
||||||
|
}
|
||||||
|
export type RootUpdatedEvent = TypedEvent<
|
||||||
|
[string, string],
|
||||||
|
RootUpdatedEventObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type RootUpdatedEventFilter = TypedEventFilter<RootUpdatedEvent>;
|
||||||
|
|
||||||
export interface ValidSignersUpdatedEventObject {
|
export interface ValidSignersUpdatedEventObject {
|
||||||
signers: string[];
|
signers: string[];
|
||||||
}
|
}
|
||||||
@ -985,6 +998,12 @@ export interface P2PIX extends BaseContract {
|
|||||||
): ReputationUpdatedEventFilter;
|
): ReputationUpdatedEventFilter;
|
||||||
ReputationUpdated(reputation?: null): ReputationUpdatedEventFilter;
|
ReputationUpdated(reputation?: null): ReputationUpdatedEventFilter;
|
||||||
|
|
||||||
|
"RootUpdated(address,bytes32)"(
|
||||||
|
seller?: null,
|
||||||
|
merkleRoot?: null
|
||||||
|
): RootUpdatedEventFilter;
|
||||||
|
RootUpdated(seller?: null, merkleRoot?: null): RootUpdatedEventFilter;
|
||||||
|
|
||||||
"ValidSignersUpdated(address[])"(
|
"ValidSignersUpdated(address[])"(
|
||||||
signers?: null
|
signers?: null
|
||||||
): ValidSignersUpdatedEventFilter;
|
): ValidSignersUpdatedEventFilter;
|
||||||
|
@ -2,13 +2,13 @@ import "@nomicfoundation/hardhat-chai-matchers";
|
|||||||
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { BigNumber, Wallet } from "ethers";
|
import { BigNumber, ContractReceipt, Wallet } from "ethers";
|
||||||
import {
|
import {
|
||||||
ethers,
|
ethers,
|
||||||
network,
|
network,
|
||||||
/* , tracer */
|
/* , tracer */
|
||||||
} from "hardhat";
|
} from "hardhat";
|
||||||
import keccak256 from "keccak256";
|
// import keccak256 from "keccak256";
|
||||||
|
|
||||||
import { MockToken, P2PIX, Reputation } from "../src/types";
|
import { MockToken, P2PIX, Reputation } from "../src/types";
|
||||||
import { P2PixErrors } from "./utils/errors";
|
import { P2PixErrors } from "./utils/errors";
|
||||||
@ -595,7 +595,7 @@ describe("P2PIX", () => {
|
|||||||
P2PixErrors.AddressDenied,
|
P2PixErrors.AddressDenied,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it ("should revert if msg.sender does not have enough credit in his spend limit", async () => {
|
it("should revert if msg.sender does not have enough credit in his spend limit", async () => {
|
||||||
await erc20.approve(p2pix.address, price);
|
await erc20.approve(p2pix.address, price);
|
||||||
await p2pix.deposit(
|
await p2pix.deposit(
|
||||||
erc20.address,
|
erc20.address,
|
||||||
@ -620,9 +620,246 @@ describe("P2PIX", () => {
|
|||||||
P2PixErrors.AmountNotAllowed,
|
P2PixErrors.AmountNotAllowed,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// it ("should create a lock, update storage and emit events via the allowlist path")
|
it("should create a lock, update storage and emit events via the allowlist path", async () => {
|
||||||
// it ("should create a lock, update storage and emit events via the reputation path")
|
await erc20.approve(p2pix.address, price);
|
||||||
// it ("should create multiple locks") - EDGE CASE TEST
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
merkleRoot,
|
||||||
|
);
|
||||||
|
const tx = await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
0,
|
||||||
|
price,
|
||||||
|
proof,
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, price, acc02.address],
|
||||||
|
);
|
||||||
|
const storage: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rc: ContractReceipt = await tx.wait();
|
||||||
|
const expiration = rc.blockNumber + 10;
|
||||||
|
|
||||||
|
expect(tx).to.be.ok;
|
||||||
|
expect(storage.depositID).to.eq(0);
|
||||||
|
expect(storage.relayerPremium).to.eq(
|
||||||
|
ethers.constants.Zero,
|
||||||
|
);
|
||||||
|
expect(storage.amount).to.eq(price);
|
||||||
|
expect(storage.expirationBlock).to.eq(expiration);
|
||||||
|
expect(storage.buyerAddress).to.eq(acc02.address);
|
||||||
|
expect(storage.relayerTarget).to.eq(acc03.address);
|
||||||
|
expect(storage.relayerAddress).to.eq(acc01.address);
|
||||||
|
await expect(tx)
|
||||||
|
.to.emit(p2pix, "LockAdded")
|
||||||
|
.withArgs(
|
||||||
|
acc02.address,
|
||||||
|
lockID,
|
||||||
|
storage.depositID,
|
||||||
|
storage.amount,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should create a lock, update storage and emit events via the reputation path", async () => {
|
||||||
|
const root = ethers.constants.HashZero;
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
root,
|
||||||
|
);
|
||||||
|
const tx = await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
const storage: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rc: ContractReceipt = await tx.wait();
|
||||||
|
const expiration = rc.blockNumber + 10;
|
||||||
|
|
||||||
|
expect(tx).to.be.ok;
|
||||||
|
expect(storage.depositID).to.eq(0);
|
||||||
|
expect(storage.relayerPremium).to.eq(
|
||||||
|
ethers.constants.Zero,
|
||||||
|
);
|
||||||
|
expect(storage.amount).to.eq(
|
||||||
|
ethers.BigNumber.from(100),
|
||||||
|
);
|
||||||
|
expect(storage.expirationBlock).to.eq(expiration);
|
||||||
|
expect(storage.buyerAddress).to.eq(acc02.address);
|
||||||
|
expect(storage.relayerTarget).to.eq(acc03.address);
|
||||||
|
expect(storage.relayerAddress).to.eq(acc01.address);
|
||||||
|
await expect(tx)
|
||||||
|
.to.emit(p2pix, "LockAdded")
|
||||||
|
.withArgs(
|
||||||
|
acc02.address,
|
||||||
|
lockID,
|
||||||
|
storage.depositID,
|
||||||
|
storage.amount,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// edge case test
|
||||||
|
it("should create multiple locks", async () => {
|
||||||
|
const newPrice = price.div(ethers.BigNumber.from(2));
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
merkleRoot,
|
||||||
|
);
|
||||||
|
const tx1 = await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
0,
|
||||||
|
newPrice,
|
||||||
|
proof,
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID1 = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, newPrice, acc02.address],
|
||||||
|
);
|
||||||
|
const storage1: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID1,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rc1: ContractReceipt = await tx1.wait();
|
||||||
|
const expiration1 = rc1.blockNumber + 10;
|
||||||
|
|
||||||
|
const tx2 = await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID2 = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
const storage2: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID2,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rc2: ContractReceipt = await tx2.wait();
|
||||||
|
const expiration2 = rc2.blockNumber + 10;
|
||||||
|
|
||||||
|
const tx3 = await p2pix
|
||||||
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc03.address,
|
||||||
|
acc03.address,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID3 = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc03.address],
|
||||||
|
);
|
||||||
|
const storage3: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID3,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rc3: ContractReceipt = await tx3.wait();
|
||||||
|
const expiration3 = rc3.blockNumber + 10;
|
||||||
|
|
||||||
|
expect(tx1).to.be.ok;
|
||||||
|
expect(tx2).to.be.ok;
|
||||||
|
expect(tx3).to.be.ok;
|
||||||
|
|
||||||
|
expect(0)
|
||||||
|
.to.eq(storage1.depositID)
|
||||||
|
.and.to.eq(storage2.depositID)
|
||||||
|
.and.to.eq(storage3.depositID);
|
||||||
|
|
||||||
|
expect(ethers.constants.Zero)
|
||||||
|
.to.eq(storage1.relayerPremium)
|
||||||
|
.and.to.eq(storage2.relayerPremium)
|
||||||
|
.and.to.eq(storage3.relayerPremium);
|
||||||
|
|
||||||
|
expect(storage1.amount).to.eq(newPrice);
|
||||||
|
expect(ethers.BigNumber.from(100))
|
||||||
|
.to.eq(storage2.amount)
|
||||||
|
.and.to.eq(storage3.amount);
|
||||||
|
|
||||||
|
expect(storage1.expirationBlock).to.eq(expiration1);
|
||||||
|
expect(storage2.expirationBlock).to.eq(expiration2);
|
||||||
|
expect(storage3.expirationBlock).to.eq(expiration3);
|
||||||
|
|
||||||
|
expect(acc02.address)
|
||||||
|
.to.eq(storage1.buyerAddress)
|
||||||
|
.and.to.eq(storage2.buyerAddress);
|
||||||
|
expect(storage3.buyerAddress).to.eq(acc03.address);
|
||||||
|
|
||||||
|
expect(acc03.address)
|
||||||
|
.to.eq(storage1.relayerTarget)
|
||||||
|
.and.to.eq(storage2.relayerTarget)
|
||||||
|
.and.to.eq(storage3.relayerTarget);
|
||||||
|
|
||||||
|
expect(acc01.address)
|
||||||
|
.to.eq(storage1.relayerAddress)
|
||||||
|
.and.to.eq(storage2.relayerAddress);
|
||||||
|
expect(storage3.relayerAddress).to.eq(acc03.address);
|
||||||
|
|
||||||
|
await expect(tx1)
|
||||||
|
.to.emit(p2pix, "LockAdded")
|
||||||
|
.withArgs(
|
||||||
|
acc02.address,
|
||||||
|
lockID1,
|
||||||
|
storage1.depositID,
|
||||||
|
storage1.amount,
|
||||||
|
);
|
||||||
|
await expect(tx2)
|
||||||
|
.to.emit(p2pix, "LockAdded")
|
||||||
|
.withArgs(
|
||||||
|
acc02.address,
|
||||||
|
lockID2,
|
||||||
|
storage2.depositID,
|
||||||
|
storage2.amount,
|
||||||
|
);
|
||||||
|
await expect(tx3)
|
||||||
|
.to.emit(p2pix, "LockAdded")
|
||||||
|
.withArgs(
|
||||||
|
acc03.address,
|
||||||
|
lockID3,
|
||||||
|
storage3.depositID,
|
||||||
|
storage3.amount,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("Cancel Deposit", async () => {
|
describe("Cancel Deposit", async () => {
|
||||||
it("should revert if the msg.sender isn't the deposit's seller", async () => {
|
it("should revert if the msg.sender isn't the deposit's seller", async () => {
|
||||||
@ -634,7 +871,10 @@ describe("P2PIX", () => {
|
|||||||
merkleRoot,
|
merkleRoot,
|
||||||
);
|
);
|
||||||
const fail = p2pix.connect(acc01).cancelDeposit(0);
|
const fail = p2pix.connect(acc01).cancelDeposit(0);
|
||||||
await expect(fail).to.be.revertedWithCustomError(p2pix, P2PixErrors.OnlySeller);
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.OnlySeller,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it("should cancel deposit, update storage and emit events", async () => {
|
it("should cancel deposit, update storage and emit events", async () => {
|
||||||
await erc20.approve(p2pix.address, price);
|
await erc20.approve(p2pix.address, price);
|
||||||
@ -644,12 +884,16 @@ describe("P2PIX", () => {
|
|||||||
"pixTarget",
|
"pixTarget",
|
||||||
merkleRoot,
|
merkleRoot,
|
||||||
);
|
);
|
||||||
const state1:Deposit = await p2pix.callStatic.mapDeposits(0);
|
const state1: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(0);
|
||||||
const tx = await p2pix.cancelDeposit(0);
|
const tx = await p2pix.cancelDeposit(0);
|
||||||
const state2:Deposit = await p2pix.callStatic.mapDeposits(0);
|
const state2: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(0);
|
||||||
|
|
||||||
expect(tx).to.be.ok;
|
expect(tx).to.be.ok;
|
||||||
await expect(tx).to.emit(p2pix, "DepositClosed").withArgs(owner.address, 0);
|
await expect(tx)
|
||||||
|
.to.emit(p2pix, "DepositClosed")
|
||||||
|
.withArgs(owner.address, 0);
|
||||||
expect(state1.valid).to.be.true;
|
expect(state1.valid).to.be.true;
|
||||||
expect(state2.valid).to.be.false;
|
expect(state2.valid).to.be.false;
|
||||||
});
|
});
|
||||||
@ -675,22 +919,34 @@ describe("P2PIX", () => {
|
|||||||
"pixTarget",
|
"pixTarget",
|
||||||
ethers.constants.HashZero,
|
ethers.constants.HashZero,
|
||||||
);
|
);
|
||||||
const oldState1:Deposit = await p2pix.callStatic.mapDeposits(0);
|
const oldState1: Deposit =
|
||||||
const oldState2:Deposit = await p2pix.callStatic.mapDeposits(1);
|
await p2pix.callStatic.mapDeposits(0);
|
||||||
const oldState3:Deposit = await p2pix.callStatic.mapDeposits(2);
|
const oldState2: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(1);
|
||||||
|
const oldState3: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(2);
|
||||||
const tx1 = await p2pix.cancelDeposit(0);
|
const tx1 = await p2pix.cancelDeposit(0);
|
||||||
const tx2 = await p2pix.cancelDeposit(1);
|
const tx2 = await p2pix.cancelDeposit(1);
|
||||||
const tx3 = await p2pix.cancelDeposit(2);
|
const tx3 = await p2pix.cancelDeposit(2);
|
||||||
const newState1:Deposit = await p2pix.callStatic.mapDeposits(0);
|
const newState1: Deposit =
|
||||||
const newState2:Deposit = await p2pix.callStatic.mapDeposits(1);
|
await p2pix.callStatic.mapDeposits(0);
|
||||||
const newState3:Deposit = await p2pix.callStatic.mapDeposits(2);
|
const newState2: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(1);
|
||||||
|
const newState3: Deposit =
|
||||||
|
await p2pix.callStatic.mapDeposits(2);
|
||||||
|
|
||||||
expect(tx1).to.be.ok;
|
expect(tx1).to.be.ok;
|
||||||
expect(tx2).to.be.ok;
|
expect(tx2).to.be.ok;
|
||||||
expect(tx3).to.be.ok;
|
expect(tx3).to.be.ok;
|
||||||
await expect(tx1).to.emit(p2pix, "DepositClosed").withArgs(owner.address, 0);
|
await expect(tx1)
|
||||||
await expect(tx2).to.emit(p2pix, "DepositClosed").withArgs(owner.address, 1);
|
.to.emit(p2pix, "DepositClosed")
|
||||||
await expect(tx3).to.emit(p2pix, "DepositClosed").withArgs(owner.address, 2);
|
.withArgs(owner.address, 0);
|
||||||
|
await expect(tx2)
|
||||||
|
.to.emit(p2pix, "DepositClosed")
|
||||||
|
.withArgs(owner.address, 1);
|
||||||
|
await expect(tx3)
|
||||||
|
.to.emit(p2pix, "DepositClosed")
|
||||||
|
.withArgs(owner.address, 2);
|
||||||
expect(oldState1.valid).to.be.true;
|
expect(oldState1.valid).to.be.true;
|
||||||
expect(oldState2.valid).to.be.true;
|
expect(oldState2.valid).to.be.true;
|
||||||
expect(oldState3.valid).to.be.true;
|
expect(oldState3.valid).to.be.true;
|
||||||
@ -712,19 +968,104 @@ describe("P2PIX", () => {
|
|||||||
// )}
|
// )}
|
||||||
});
|
});
|
||||||
describe("Unexpire Locks", async () => {
|
describe("Unexpire Locks", async () => {
|
||||||
// it("should revert if lock isn't expired")
|
it("should revert if lock isn't expired", async () => {
|
||||||
// it("should unlock expired locks, update storage and emit events")
|
await erc20.approve(p2pix.address, price);
|
||||||
// CHECK FOR userRecord STORAGE UPDATE
|
await p2pix.deposit(
|
||||||
// test method through lock fx
|
erc20.address,
|
||||||
// test method through withdraw fx
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
merkleRoot,
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc02)
|
||||||
|
.lock(0, acc02.address, acc03.address, 0, 1, [], []);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 1, acc02.address],
|
||||||
|
);
|
||||||
|
const fail = p2pix.unlockExpired([lockID]);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.NotExpired,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should unlock expired locks, update storage and emit events", async () => {
|
||||||
|
// CHECK FOR userRecord STORAGE UPDATE
|
||||||
|
// test method through lock fx
|
||||||
|
// test method through withdraw fx
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("Seller Withdraw", async () => {
|
describe("Seller Withdraw", async () => {
|
||||||
// it("should revert if the msg.sender isn't the deposit's seller")
|
it("should revert if the msg.sender isn't the deposit's seller", async () => {
|
||||||
// it -> withdraw remaining funds from deposit
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
merkleRoot,
|
||||||
|
);
|
||||||
|
const fail = p2pix.connect(acc02).withdraw(0, []);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.OnlySeller,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should withdraw remaining funds from deposit, update storage and emit event", async () => {
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
const dep = await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
merkleRoot,
|
||||||
|
);
|
||||||
|
const tx = await p2pix.withdraw(0, []);
|
||||||
|
|
||||||
|
expect(tx).to.be.ok;
|
||||||
|
await expect(dep)
|
||||||
|
.to.changeTokenBalance(
|
||||||
|
erc20,
|
||||||
|
owner.address,
|
||||||
|
"-100000000000000000000",
|
||||||
|
)
|
||||||
|
.and.to.changeTokenBalance(
|
||||||
|
erc20,
|
||||||
|
p2pix.address,
|
||||||
|
price,
|
||||||
|
);
|
||||||
|
await expect(tx)
|
||||||
|
.to.changeTokenBalance(erc20, owner.address, price)
|
||||||
|
.and.to.changeTokenBalance(
|
||||||
|
erc20,
|
||||||
|
p2pix.address,
|
||||||
|
"-100000000000000000000",
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(tx)
|
||||||
|
.to.emit(p2pix, "DepositWithdrawn")
|
||||||
|
.withArgs(owner.address, 0, price);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("Allowlist Settings", async () => {
|
describe("Allowlist Settings", async () => {
|
||||||
// it -> set root of seller's allowlist
|
it(" should revert if the msg.sender differs from deposit's seller", async () => {
|
||||||
// (test msg.sender != seller error)
|
const root = ethers.utils.keccak256(
|
||||||
// i.e., set it in the fixture
|
ethers.utils.toUtf8Bytes("root"),
|
||||||
|
);
|
||||||
|
const fail = p2pix.connect(acc02).setRoot(owner.address, root);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(p2pix, P2PixErrors.OnlySeller);
|
||||||
|
});
|
||||||
|
it("should set root of seller's allowlist, update storage and emit event", async () => {
|
||||||
|
const ownerKey = await p2pix.callStatic._castAddrToKey(owner.address);
|
||||||
|
const oldState = await p2pix.callStatic.sellerAllowList(ownerKey);
|
||||||
|
const tx = await p2pix.connect(owner).setRoot(owner.address, merkleRoot);
|
||||||
|
const newState = await p2pix.callStatic.sellerAllowList(ownerKey);
|
||||||
|
|
||||||
|
expect(tx).to.be.ok;
|
||||||
|
await expect(tx).to.emit(p2pix, "RootUpdated").withArgs(owner.address, merkleRoot);
|
||||||
|
expect(oldState).to.eq(ethers.constants.HashZero);
|
||||||
|
expect(newState).to.eq(merkleRoot);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,11 @@ import {
|
|||||||
} from "../../src/types";
|
} from "../../src/types";
|
||||||
|
|
||||||
// exported interfaces
|
// exported interfaces
|
||||||
|
export interface Deploys {
|
||||||
|
signers: string[];
|
||||||
|
p2pix: string;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Deposit {
|
export interface Deposit {
|
||||||
remaining: BigNumber;
|
remaining: BigNumber;
|
||||||
@ -21,10 +26,10 @@ export interface Deposit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Lock {
|
export interface Lock {
|
||||||
depositID: string;
|
depositID: BigNumber;
|
||||||
relayerPremium: string;
|
relayerPremium: BigNumber;
|
||||||
amount: string;
|
amount: BigNumber;
|
||||||
expirationBlock: string;
|
expirationBlock: BigNumber;
|
||||||
buyerAddress: string;
|
buyerAddress: string;
|
||||||
relayerTarget: string;
|
relayerTarget: string;
|
||||||
relayerAddress: string;
|
relayerAddress: string;
|
||||||
@ -130,7 +135,7 @@ export async function p2pixFixture(): Promise<P2PixAndReputation> {
|
|||||||
});
|
});
|
||||||
const merkleRoot: string = tree.getHexRoot();
|
const merkleRoot: string = tree.getHexRoot();
|
||||||
const proof: string[] = tree.getHexProof(
|
const proof: string[] = tree.getHexProof(
|
||||||
padBuffer(whitelisted[0].address),
|
padBuffer(whitelisted[1].address),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
21
yarn.lock
21
yarn.lock
@ -3495,6 +3495,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"chalk@npm:4.x, chalk@npm:^4.1.1":
|
||||||
|
version: 4.1.2
|
||||||
|
resolution: "chalk@npm:4.1.2"
|
||||||
|
dependencies:
|
||||||
|
ansi-styles: ^4.1.0
|
||||||
|
supports-color: ^7.1.0
|
||||||
|
checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"chalk@npm:^2.0.0, chalk@npm:^2.1.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2":
|
"chalk@npm:^2.0.0, chalk@npm:^2.1.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2":
|
||||||
version: 2.4.2
|
version: 2.4.2
|
||||||
resolution: "chalk@npm:2.4.2"
|
resolution: "chalk@npm:2.4.2"
|
||||||
@ -3516,16 +3526,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"chalk@npm:^4.1.1":
|
|
||||||
version: 4.1.2
|
|
||||||
resolution: "chalk@npm:4.1.2"
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: ^4.1.0
|
|
||||||
supports-color: ^7.1.0
|
|
||||||
checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"chardet@npm:^0.7.0":
|
"chardet@npm:^0.7.0":
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
resolution: "chardet@npm:0.7.0"
|
resolution: "chardet@npm:0.7.0"
|
||||||
@ -8448,6 +8448,7 @@ fsevents@~2.1.1:
|
|||||||
"@typescript-eslint/eslint-plugin": ^5.42.0
|
"@typescript-eslint/eslint-plugin": ^5.42.0
|
||||||
"@typescript-eslint/parser": ^5.42.0
|
"@typescript-eslint/parser": ^5.42.0
|
||||||
chai: ^4.3.6
|
chai: ^4.3.6
|
||||||
|
chalk: 4.x
|
||||||
commitizen: ^4.2.5
|
commitizen: ^4.2.5
|
||||||
cross-env: ^7.0.3
|
cross-env: ^7.0.3
|
||||||
cz-conventional-changelog: ^3.3.0
|
cz-conventional-changelog: ^3.3.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user