fix: release FX fixed and unit tests added
This commit is contained in:
parent
932b2a03b4
commit
d2b4e21241
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../build-info/10314198dd1b1c93bdb3afe5190d4fa3.json"
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
"name": "LengthMismatch",
|
"name": "LengthMismatch",
|
||||||
"type": "error"
|
"type": "error"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "LockExpired",
|
||||||
|
"type": "error"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"name": "LoopOverflow",
|
"name": "LoopOverflow",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../../../build-info/8b1c16bb48b706a49fa1987390ca36fd.json"
|
"buildInfo": "../../../../build-info/246d885849ebe73a8f97a386ac3822ea.json"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/43c90b4df62900d52ce9b2809e9d7089.json"
|
"buildInfo": "../../build-info/a7ece494b4784ac2499b0ced3d2c9c0a.json"
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -100,4 +100,7 @@ interface EventAndErrors {
|
|||||||
/// @dev Reverts when success return value returns false.
|
/// @dev Reverts when success return value returns false.
|
||||||
/// @dev 0xe10bf1cc
|
/// @dev 0xe10bf1cc
|
||||||
error StaticCallFailed();
|
error StaticCallFailed();
|
||||||
|
/// @dev Reverts on an expired lock.
|
||||||
|
/// @dev 0xf6fafba0
|
||||||
|
error LockExpired();
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ contract P2PIX is
|
|||||||
/// @dev List of Locks.
|
/// @dev List of Locks.
|
||||||
mapping(bytes32 => DT.Lock) public mapLocks;
|
mapping(bytes32 => DT.Lock) public mapLocks;
|
||||||
/// @dev List of Pix transactions already signed.
|
/// @dev List of Pix transactions already signed.
|
||||||
mapping(bytes32 => bool) private usedTransactions;
|
mapping(bytes32 => bool) public usedTransactions;
|
||||||
/// @dev Seller casted to key => Seller's allowlist merkleroot.
|
/// @dev Seller casted to key => Seller's allowlist merkleroot.
|
||||||
mapping(uint256 => bytes32) public sellerAllowList;
|
mapping(uint256 => bytes32) public sellerAllowList;
|
||||||
/// @dev Tokens allowed to serve as the underlying amount of a deposit.
|
/// @dev Tokens allowed to serve as the underlying amount of a deposit.
|
||||||
@ -243,9 +243,12 @@ contract P2PIX is
|
|||||||
) public nonReentrant {
|
) public nonReentrant {
|
||||||
DT.Lock storage l = mapLocks[lockID];
|
DT.Lock storage l = mapLocks[lockID];
|
||||||
|
|
||||||
if (
|
// if (
|
||||||
l.expirationBlock <= block.number || l.amount <= 0
|
// l.expirationBlock <= block.number || l.amount <= 0
|
||||||
) revert AlreadyReleased();
|
// ) revert AlreadyReleased();
|
||||||
|
if (l.amount == 0) revert AlreadyReleased();
|
||||||
|
if (l.expirationBlock < block.number)
|
||||||
|
revert LockExpired();
|
||||||
|
|
||||||
DT.Deposit storage d = mapDeposits[l.depositID];
|
DT.Deposit storage d = mapDeposits[l.depositID];
|
||||||
bytes32 message = keccak256(
|
bytes32 message = keccak256(
|
||||||
@ -275,7 +278,8 @@ contract P2PIX is
|
|||||||
ERC20 t = ERC20(d.token);
|
ERC20 t = ERC20(d.token);
|
||||||
|
|
||||||
// We cache values before zeroing them out.
|
// We cache values before zeroing them out.
|
||||||
uint256 totalAmount = (l.amount - l.relayerPremium);
|
uint256 lockAmount = l.amount;
|
||||||
|
uint256 totalAmount = (lockAmount - l.relayerPremium);
|
||||||
|
|
||||||
l.amount = 0;
|
l.amount = 0;
|
||||||
l.expirationBlock = 0;
|
l.expirationBlock = 0;
|
||||||
@ -284,11 +288,12 @@ contract P2PIX is
|
|||||||
if (msg.sender != l.relayerAddress) {
|
if (msg.sender != l.relayerAddress) {
|
||||||
userRecord[_castAddrToKey(msg.sender)] += l
|
userRecord[_castAddrToKey(msg.sender)] += l
|
||||||
.relayerPremium;
|
.relayerPremium;
|
||||||
userRecord[_castAddrToKey(l.relayerAddress)] += l
|
userRecord[
|
||||||
.amount;
|
_castAddrToKey(l.relayerAddress)
|
||||||
|
] += lockAmount;
|
||||||
} else {
|
} else {
|
||||||
userRecord[_castAddrToKey(msg.sender)] += (l
|
userRecord[_castAddrToKey(msg.sender)] += (l
|
||||||
.relayerPremium + l.amount);
|
.relayerPremium + lockAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeTransferLib.safeTransfer(
|
SafeTransferLib.safeTransfer(
|
||||||
|
@ -5,4 +5,4 @@
|
|||||||
],
|
],
|
||||||
"p2pix": "0x37c856F4d5bC2597da60f607b1335738468453F3",
|
"p2pix": "0x37c856F4d5bC2597da60f607b1335738468453F3",
|
||||||
"token": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee"
|
"token": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee"
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@ const _abi = [
|
|||||||
name: "LengthMismatch",
|
name: "LengthMismatch",
|
||||||
type: "error",
|
type: "error",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "LockExpired",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
inputs: [],
|
inputs: [],
|
||||||
name: "LoopOverflow",
|
name: "LoopOverflow",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -49,6 +49,7 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
"setValidSigners(address[])": FunctionFragment;
|
"setValidSigners(address[])": FunctionFragment;
|
||||||
"tokenSettings(address[],bool[])": FunctionFragment;
|
"tokenSettings(address[],bool[])": FunctionFragment;
|
||||||
"unlockExpired(bytes32[])": FunctionFragment;
|
"unlockExpired(bytes32[])": FunctionFragment;
|
||||||
|
"usedTransactions(bytes32)": FunctionFragment;
|
||||||
"userRecord(uint256)": FunctionFragment;
|
"userRecord(uint256)": FunctionFragment;
|
||||||
"validBacenSigners(uint256)": FunctionFragment;
|
"validBacenSigners(uint256)": FunctionFragment;
|
||||||
"withdraw(uint256,bytes32[])": FunctionFragment;
|
"withdraw(uint256,bytes32[])": FunctionFragment;
|
||||||
@ -77,6 +78,7 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
| "setValidSigners"
|
| "setValidSigners"
|
||||||
| "tokenSettings"
|
| "tokenSettings"
|
||||||
| "unlockExpired"
|
| "unlockExpired"
|
||||||
|
| "usedTransactions"
|
||||||
| "userRecord"
|
| "userRecord"
|
||||||
| "validBacenSigners"
|
| "validBacenSigners"
|
||||||
| "withdraw"
|
| "withdraw"
|
||||||
@ -180,6 +182,10 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
functionFragment: "unlockExpired",
|
functionFragment: "unlockExpired",
|
||||||
values: [PromiseOrValue<BytesLike>[]]
|
values: [PromiseOrValue<BytesLike>[]]
|
||||||
): string;
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "usedTransactions",
|
||||||
|
values: [PromiseOrValue<BytesLike>]
|
||||||
|
): string;
|
||||||
encodeFunctionData(
|
encodeFunctionData(
|
||||||
functionFragment: "userRecord",
|
functionFragment: "userRecord",
|
||||||
values: [PromiseOrValue<BigNumberish>]
|
values: [PromiseOrValue<BigNumberish>]
|
||||||
@ -253,6 +259,10 @@ export interface P2PIXInterface extends utils.Interface {
|
|||||||
functionFragment: "unlockExpired",
|
functionFragment: "unlockExpired",
|
||||||
data: BytesLike
|
data: BytesLike
|
||||||
): Result;
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "usedTransactions",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
decodeFunctionResult(functionFragment: "userRecord", data: BytesLike): Result;
|
decodeFunctionResult(functionFragment: "userRecord", data: BytesLike): Result;
|
||||||
decodeFunctionResult(
|
decodeFunctionResult(
|
||||||
functionFragment: "validBacenSigners",
|
functionFragment: "validBacenSigners",
|
||||||
@ -596,6 +606,11 @@ export interface P2PIX extends BaseContract {
|
|||||||
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
||||||
): Promise<ContractTransaction>;
|
): Promise<ContractTransaction>;
|
||||||
|
|
||||||
|
usedTransactions(
|
||||||
|
arg0: PromiseOrValue<BytesLike>,
|
||||||
|
overrides?: CallOverrides
|
||||||
|
): Promise<[boolean]>;
|
||||||
|
|
||||||
userRecord(
|
userRecord(
|
||||||
arg0: PromiseOrValue<BigNumberish>,
|
arg0: PromiseOrValue<BigNumberish>,
|
||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
@ -739,6 +754,11 @@ export interface P2PIX extends BaseContract {
|
|||||||
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
||||||
): Promise<ContractTransaction>;
|
): Promise<ContractTransaction>;
|
||||||
|
|
||||||
|
usedTransactions(
|
||||||
|
arg0: PromiseOrValue<BytesLike>,
|
||||||
|
overrides?: CallOverrides
|
||||||
|
): Promise<boolean>;
|
||||||
|
|
||||||
userRecord(
|
userRecord(
|
||||||
arg0: PromiseOrValue<BigNumberish>,
|
arg0: PromiseOrValue<BigNumberish>,
|
||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
@ -882,6 +902,11 @@ export interface P2PIX extends BaseContract {
|
|||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
|
|
||||||
|
usedTransactions(
|
||||||
|
arg0: PromiseOrValue<BytesLike>,
|
||||||
|
overrides?: CallOverrides
|
||||||
|
): Promise<boolean>;
|
||||||
|
|
||||||
userRecord(
|
userRecord(
|
||||||
arg0: PromiseOrValue<BigNumberish>,
|
arg0: PromiseOrValue<BigNumberish>,
|
||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
@ -1115,6 +1140,11 @@ export interface P2PIX extends BaseContract {
|
|||||||
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
||||||
): Promise<BigNumber>;
|
): Promise<BigNumber>;
|
||||||
|
|
||||||
|
usedTransactions(
|
||||||
|
arg0: PromiseOrValue<BytesLike>,
|
||||||
|
overrides?: CallOverrides
|
||||||
|
): Promise<BigNumber>;
|
||||||
|
|
||||||
userRecord(
|
userRecord(
|
||||||
arg0: PromiseOrValue<BigNumberish>,
|
arg0: PromiseOrValue<BigNumberish>,
|
||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
@ -1241,6 +1271,11 @@ export interface P2PIX extends BaseContract {
|
|||||||
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
overrides?: Overrides & { from?: PromiseOrValue<string> }
|
||||||
): Promise<PopulatedTransaction>;
|
): Promise<PopulatedTransaction>;
|
||||||
|
|
||||||
|
usedTransactions(
|
||||||
|
arg0: PromiseOrValue<BytesLike>,
|
||||||
|
overrides?: CallOverrides
|
||||||
|
): Promise<PopulatedTransaction>;
|
||||||
|
|
||||||
userRecord(
|
userRecord(
|
||||||
arg0: PromiseOrValue<BigNumberish>,
|
arg0: PromiseOrValue<BigNumberish>,
|
||||||
overrides?: CallOverrides
|
overrides?: CallOverrides
|
||||||
|
@ -944,69 +944,345 @@ describe("P2PIX", () => {
|
|||||||
expect(newState3.valid).to.be.false;
|
expect(newState3.valid).to.be.false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// describe("Release", async () => {
|
describe("Release", async () => {
|
||||||
// // it("should revert if lock has expired or has already been released")
|
it("should revert if lock has expired", async () => {
|
||||||
// // it("should revert if signed message has already been used")
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
// // it("should revert if ecrecovered signer is invalid")
|
["string", "uint256", "uint256"],
|
||||||
// // // @todo Finish storage and event checks
|
["pixTarget", 100, "1337"],
|
||||||
// // it("should release lock, update storage and emit events", async () => {
|
);
|
||||||
// // const endtoendID = "124";
|
const flatSig = await acc01.signMessage(
|
||||||
// // const pixTarget = "pixTarget";
|
ethers.utils.arrayify(messageToSign),
|
||||||
// // const messageToSign = ethers.utils.solidityKeccak256(
|
);
|
||||||
// // ["string", "uint256", "uint256"],
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
// // [pixTarget, 100, endtoendID],
|
await erc20.approve(p2pix.address, price);
|
||||||
// // );
|
await p2pix.deposit(
|
||||||
// // const messageHashBytes =
|
erc20.address,
|
||||||
// // ethers.utils.arrayify(messageToSign);
|
price,
|
||||||
// // const flatSig = await acc01.signMessage(
|
"pixTarget",
|
||||||
// // messageHashBytes,
|
merkleRoot,
|
||||||
// // );
|
);
|
||||||
// // const sig = ethers.utils.splitSignature(flatSig);
|
await p2pix
|
||||||
// // const root = ethers.constants.HashZero;
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
6,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
await mine(13);
|
||||||
|
const fail = p2pix.release(
|
||||||
|
lockID,
|
||||||
|
acc03.address,
|
||||||
|
"1337",
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
|
||||||
// // await erc20.approve(p2pix.address, price);
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
// // await p2pix.deposit(
|
p2pix,
|
||||||
// // erc20.address,
|
P2PixErrors.LockExpired,
|
||||||
// // price,
|
);
|
||||||
// // pixTarget,
|
});
|
||||||
// // root,
|
it("should revert if lock has already been released", async () => {
|
||||||
// // );
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
// // await p2pix
|
["string", "uint256", "uint256"],
|
||||||
// // .connect(acc01)
|
["pixTarget", 100, "1337"],
|
||||||
// // .lock(
|
);
|
||||||
// // 0,
|
const flatSig = await acc01.signMessage(
|
||||||
// // acc02.address,
|
ethers.utils.arrayify(messageToSign),
|
||||||
// // acc03.address,
|
);
|
||||||
// // 0,
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
// // 100,
|
await erc20.approve(p2pix.address, price);
|
||||||
// // [],
|
await p2pix.deposit(
|
||||||
// // [],
|
erc20.address,
|
||||||
// // );
|
price,
|
||||||
// // const lockID = ethers.utils.solidityKeccak256(
|
"pixTarget",
|
||||||
// // ["uint256", "uint256", "address"],
|
merkleRoot,
|
||||||
// // [0, 100, acc02.address],
|
);
|
||||||
// // );
|
await p2pix
|
||||||
// // const storage1: Lock = await p2pix.callStatic.mapLocks(
|
.connect(acc03)
|
||||||
// // lockID,
|
.lock(
|
||||||
// // );
|
0,
|
||||||
// // const tx = await p2pix
|
acc02.address,
|
||||||
// // .connect(acc01)
|
acc03.address,
|
||||||
// // .release(
|
6,
|
||||||
// // lockID,
|
100,
|
||||||
// // acc03.address,
|
[],
|
||||||
// // endtoendID,
|
[],
|
||||||
// // sig.r,
|
);
|
||||||
// // sig.s,
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
// // sig.v,
|
["uint256", "uint256", "address"],
|
||||||
// // );
|
[0, 100, acc02.address],
|
||||||
// // });
|
);
|
||||||
// // it("should release multiple locks") - EDGE CASE TEST {
|
await p2pix.release(
|
||||||
// // TEST 3 CASES (
|
lockID,
|
||||||
// // EMPTY PREMIUM,
|
acc03.address,
|
||||||
// // LOCK RELAYER != RELEASE RELAYER, (check userRecord storage update)
|
"1337",
|
||||||
// // LOCK RELAYER == RELEASE RELAYER (check userRecord storage update)
|
sig.r,
|
||||||
// // )}
|
sig.s,
|
||||||
// });
|
sig.v,
|
||||||
|
);
|
||||||
|
const fail = p2pix.release(
|
||||||
|
lockID,
|
||||||
|
acc03.address,
|
||||||
|
"1337",
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.AlreadyReleased,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should revert if signed message has already been used", async () => {
|
||||||
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
|
["string", "uint256", "uint256"],
|
||||||
|
["pixTarget", 100, "1337"],
|
||||||
|
);
|
||||||
|
const flatSig = await owner.signMessage(
|
||||||
|
ethers.utils.arrayify(messageToSign),
|
||||||
|
);
|
||||||
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
ethers.constants.HashZero,
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
6,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.release(
|
||||||
|
lockID,
|
||||||
|
acc02.address,
|
||||||
|
"1337",
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
6,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID2 = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
const fail = p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.release(
|
||||||
|
lockID2,
|
||||||
|
acc02.address,
|
||||||
|
"1337",
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.TxAlreadyUsed,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should revert if ecrecovered signer is invalid", async () => {
|
||||||
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
|
["string", "uint256", "uint256"],
|
||||||
|
["pixTarget", 100, "1337"],
|
||||||
|
);
|
||||||
|
const flatSig = await acc03.signMessage(
|
||||||
|
ethers.utils.arrayify(messageToSign),
|
||||||
|
);
|
||||||
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
|
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
"pixTarget",
|
||||||
|
ethers.constants.HashZero,
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
6,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
const fail = p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.release(
|
||||||
|
lockID,
|
||||||
|
acc02.address,
|
||||||
|
"1337",
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fail).to.be.revertedWithCustomError(
|
||||||
|
p2pix,
|
||||||
|
P2PixErrors.InvalidSigner,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should release lock, update storage and emit events", async () => {
|
||||||
|
const endtoendID = "124";
|
||||||
|
const pixTarget = "pixTarget";
|
||||||
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
|
["string", "uint256", "uint256"],
|
||||||
|
[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
|
||||||
|
// the string represents
|
||||||
|
//
|
||||||
|
// i.e.,
|
||||||
|
// 66-byte string
|
||||||
|
// "0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba"
|
||||||
|
// ... vs ...
|
||||||
|
// 32 entry Uint8Array
|
||||||
|
// [ 89, 47, 167, 67, 136, 159, ... 103, 7, 186]
|
||||||
|
const messageHashBytes =
|
||||||
|
ethers.utils.arrayify(messageToSign);
|
||||||
|
const flatSig = await acc01.signMessage(
|
||||||
|
messageHashBytes,
|
||||||
|
);
|
||||||
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
|
const root = ethers.constants.HashZero;
|
||||||
|
|
||||||
|
await erc20.approve(p2pix.address, price);
|
||||||
|
await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
price,
|
||||||
|
pixTarget,
|
||||||
|
root,
|
||||||
|
);
|
||||||
|
await p2pix
|
||||||
|
.connect(acc03)
|
||||||
|
.lock(
|
||||||
|
0,
|
||||||
|
acc02.address,
|
||||||
|
acc03.address,
|
||||||
|
6,
|
||||||
|
100,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(
|
||||||
|
["uint256", "uint256", "address"],
|
||||||
|
[0, 100, acc02.address],
|
||||||
|
);
|
||||||
|
const acc01Key = await p2pix.callStatic._castAddrToKey(
|
||||||
|
acc01.address,
|
||||||
|
);
|
||||||
|
const acc03Key = await p2pix.callStatic._castAddrToKey(
|
||||||
|
acc03.address,
|
||||||
|
);
|
||||||
|
const userRecordA = await p2pix.callStatic.userRecord(
|
||||||
|
acc01Key,
|
||||||
|
);
|
||||||
|
const userRecord1 = await p2pix.callStatic.userRecord(
|
||||||
|
acc03Key,
|
||||||
|
);
|
||||||
|
const storage1: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID,
|
||||||
|
);
|
||||||
|
const tx = await p2pix
|
||||||
|
.connect(acc01)
|
||||||
|
.release(
|
||||||
|
lockID,
|
||||||
|
acc02.address,
|
||||||
|
endtoendID,
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v,
|
||||||
|
);
|
||||||
|
const storage2: Lock = await p2pix.callStatic.mapLocks(
|
||||||
|
lockID,
|
||||||
|
);
|
||||||
|
const userRecordB = await p2pix.callStatic.userRecord(
|
||||||
|
acc01Key,
|
||||||
|
);
|
||||||
|
const userRecord2 = await p2pix.callStatic.userRecord(
|
||||||
|
acc03Key,
|
||||||
|
);
|
||||||
|
const used = await p2pix.callStatic.usedTransactions(
|
||||||
|
messageHashBytes,
|
||||||
|
);
|
||||||
|
expect(tx).to.be.ok;
|
||||||
|
await expect(tx)
|
||||||
|
.to.emit(p2pix, "LockReleased")
|
||||||
|
.withArgs(acc02.address, lockID);
|
||||||
|
expect(storage1.expirationBlock).to.eq(
|
||||||
|
ethers.BigNumber.from(16),
|
||||||
|
);
|
||||||
|
expect(storage1.amount).to.eq(
|
||||||
|
ethers.BigNumber.from(100),
|
||||||
|
);
|
||||||
|
expect(storage2.expirationBlock).to.eq(
|
||||||
|
ethers.BigNumber.from(0),
|
||||||
|
);
|
||||||
|
expect(storage2.amount).to.eq(ethers.BigNumber.from(0));
|
||||||
|
expect(used).to.eq(true);
|
||||||
|
expect(userRecordA).to.eq(ethers.constants.Zero);
|
||||||
|
expect(userRecord1).to.eq(ethers.constants.Zero);
|
||||||
|
expect(userRecordB).to.eq(ethers.BigNumber.from(6));
|
||||||
|
expect(userRecord2).to.eq(ethers.BigNumber.from(100));
|
||||||
|
await expect(tx).to.changeTokenBalances(
|
||||||
|
erc20,
|
||||||
|
[acc03.address, acc02.address],
|
||||||
|
[3, 97],
|
||||||
|
// acc02 is acting both as buyer and relayerTarget
|
||||||
|
// (i.e., 94 + 3 = 97)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
/// @todo
|
||||||
|
// it("should release multiple locks") - EDGE CASE TEST {
|
||||||
|
// TEST 3 CASES (
|
||||||
|
// EMPTY PREMIUM,
|
||||||
|
// LOCK RELAYER != RELEASE RELAYER, (check userRecord storage update)
|
||||||
|
// LOCK RELAYER == RELEASE RELAYER (check userRecord storage update)
|
||||||
|
// )}
|
||||||
|
});
|
||||||
describe("Unexpire Locks", async () => {
|
describe("Unexpire Locks", async () => {
|
||||||
it("should revert if lock isn't expired", async () => {
|
it("should revert if lock isn't expired", async () => {
|
||||||
await erc20.approve(p2pix.address, price);
|
await erc20.approve(p2pix.address, price);
|
||||||
@ -1059,8 +1335,8 @@ describe("P2PIX", () => {
|
|||||||
);
|
);
|
||||||
// await mine(10);
|
// await mine(10);
|
||||||
await p2pix.release(
|
await p2pix.release(
|
||||||
lockID,
|
lockID,
|
||||||
acc03.address,
|
acc03.address,
|
||||||
endtoendID,
|
endtoendID,
|
||||||
sig.r,
|
sig.r,
|
||||||
sig.s,
|
sig.s,
|
||||||
@ -1281,7 +1557,7 @@ describe("P2PIX", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("Allowlist Settings", async () => {
|
describe("Allowlist Settings", async () => {
|
||||||
it(" should revert if the msg.sender differs from deposit's seller", async () => {
|
it("should revert if the msg.sender differs from deposit's seller", async () => {
|
||||||
const root = ethers.utils.keccak256(
|
const root = ethers.utils.keccak256(
|
||||||
ethers.utils.toUtf8Bytes("root"),
|
ethers.utils.toUtf8Bytes("root"),
|
||||||
);
|
);
|
||||||
|
@ -14,4 +14,5 @@ export enum P2PixErrors {
|
|||||||
LengthMismatch = "LengthMismatch",
|
LengthMismatch = "LengthMismatch",
|
||||||
AddressDenied = "AddressDenied",
|
AddressDenied = "AddressDenied",
|
||||||
AmountNotAllowed = "AmountNotAllowed",
|
AmountNotAllowed = "AmountNotAllowed",
|
||||||
|
LockExpired = "LockExpired",
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user