Compare commits
2 Commits
dev
...
feature_bo
Author | SHA1 | Date |
---|---|---|
hueso | 4a4a18121c | |
hueso | 9b6617a702 |
|
@ -44,4 +44,5 @@ abstract contract Constants {
|
|||
uint256 constant MAXBALANCE_UPPERBOUND = 1e8 ether;
|
||||
uint256 constant REPUTATION_LOWERBOUND = 1e2 ether;
|
||||
uint256 constant LOCKAMOUNT_UPPERBOUND = 1e6 ether;
|
||||
uint256 constant BOND_DIVISOR = 4; // 6,25%
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ library DataTypes {
|
|||
ERC20 token;
|
||||
address buyerAddress;
|
||||
address seller;
|
||||
bool bond;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
|
|
|
@ -135,7 +135,8 @@ contract P2PIX is BaseUtils {
|
|||
ERC20 token,
|
||||
uint80 amount,
|
||||
bytes32[] calldata merkleProof,
|
||||
uint256[] calldata expiredLocks
|
||||
uint256[] calldata expiredLocks,
|
||||
bool bond
|
||||
) public nonReentrant returns (uint256 lockID) {
|
||||
unlockExpired(expiredLocks);
|
||||
|
||||
|
@ -154,10 +155,17 @@ contract P2PIX is BaseUtils {
|
|||
|
||||
bytes32 _pixTarget = getPixTarget(seller, token);
|
||||
|
||||
// transaction forwarding must leave `merkleProof` empty;
|
||||
// otherwise, the trustedForwarder must be previously added
|
||||
// to a seller whitelist.
|
||||
if (merkleProof.length != 0) {
|
||||
if (bond){
|
||||
SafeTransferLib.safeTransferFrom(
|
||||
token,
|
||||
_msgSender(),
|
||||
address(this),
|
||||
amount >> BOND_DIVISOR
|
||||
);
|
||||
} else if (merkleProof.length != 0) {
|
||||
// transaction forwarding must leave `merkleProof` empty;
|
||||
// otherwise, the trustedForwarder must be previously added
|
||||
// to a seller whitelist.
|
||||
_merkleVerify( merkleProof, sellerAllowList(seller), _msgSender());
|
||||
|
||||
} else if ( amount > REPUTATION_LOWERBOUND && msg.sender == _msgSender() ) {
|
||||
|
@ -178,7 +186,8 @@ contract P2PIX is BaseUtils {
|
|||
amount,
|
||||
token,
|
||||
_msgSender(),
|
||||
seller
|
||||
seller,
|
||||
bond
|
||||
);
|
||||
|
||||
_addLock(bal, l);
|
||||
|
@ -237,7 +246,7 @@ contract P2PIX is BaseUtils {
|
|||
SafeTransferLib.safeTransfer(
|
||||
t,
|
||||
l.buyerAddress,
|
||||
lockAmount
|
||||
l.bond ? lockAmount + lockAmount >> BOND_DIVISOR : lockAmount
|
||||
);
|
||||
|
||||
emit LockReleased(l.buyerAddress, lockID, lockAmount);
|
||||
|
@ -266,7 +275,7 @@ contract P2PIX is BaseUtils {
|
|||
if ((_sellerBalance + l.amount) > MAXBALANCE_UPPERBOUND)
|
||||
revert MaxBalExceeded();
|
||||
|
||||
_addSellerBalance(l.seller, l.token, l.amount);
|
||||
_addSellerBalance(l.seller, l.token, l.bond ? l.amount + l.amount >> BOND_DIVISOR : l.amount);
|
||||
|
||||
l.amount = 0;
|
||||
|
||||
|
|
|
@ -94,3 +94,9 @@ uint256 REPUTATION_LOWERBOUND
|
|||
uint256 LOCKAMOUNT_UPPERBOUND
|
||||
```
|
||||
|
||||
### BOND_DIVISOR
|
||||
|
||||
```solidity
|
||||
uint256 BOND_DIVISOR
|
||||
```
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ struct Lock {
|
|||
contract ERC20 token;
|
||||
address buyerAddress;
|
||||
address seller;
|
||||
bool bond;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ _Function sighash: 0x6d82d9e0_
|
|||
### lock
|
||||
|
||||
```solidity
|
||||
function lock(address seller, contract ERC20 token, uint80 amount, bytes32[] merkleProof, uint256[] expiredLocks) public returns (uint256 lockID)
|
||||
function lock(address seller, contract ERC20 token, uint80 amount, bytes32[] merkleProof, uint256[] expiredLocks, bool bond) public returns (uint256 lockID)
|
||||
```
|
||||
|
||||
Public method designed to lock an remaining amount of
|
||||
|
@ -78,7 +78,7 @@ to a seller whitelist.
|
|||
This method can be performed either by:
|
||||
- An user allowed via the seller's allowlist;
|
||||
- An user with enough userRecord to lock the wished amount;
|
||||
There can only exist a lock per each `_amount` partitioned
|
||||
There can only exist a lock per each `amount` partitioned
|
||||
from the total `remaining` value.
|
||||
Locks can only be performed in valid orders.
|
||||
|
||||
|
@ -93,6 +93,7 @@ _Function sighash: 0xdc43221c_
|
|||
| amount | uint80 | The deposit's remaining amount wished to be locked. |
|
||||
| merkleProof | bytes32[] | Provided as a pass if the `msg.sender` is in the seller's allowlist; Left empty otherwise; |
|
||||
| expiredLocks | uint256[] | An array of identifiers to be provided so to unexpire locks using this transaction gas push. |
|
||||
| bond | bool | |
|
||||
|
||||
#### Return Values
|
||||
|
||||
|
|
|
@ -622,6 +622,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const fail2 = p2pix.lock(
|
||||
zero,
|
||||
|
@ -629,6 +630,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
await expect(fail).to.be.revertedWithCustomError(
|
||||
|
@ -658,6 +660,7 @@ describe("P2PIX", () => {
|
|||
price.mul(ethers.BigNumber.from(2)),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
await expect(fail).to.be.revertedWithCustomError(
|
||||
|
@ -683,6 +686,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(1000),
|
||||
[ethers.utils.keccak256(ethers.utils.toUtf8Bytes("wrong"))],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
await expect(fail).to.be.revertedWithCustomError(
|
||||
|
@ -710,6 +714,7 @@ describe("P2PIX", () => {
|
|||
price.mul(2),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
await expect(fail).to.be.revertedWithCustomError(
|
||||
|
@ -717,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);
|
||||
|
@ -735,6 +776,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
proof,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage: Lock = await p2pix.callStatic.mapLocks(
|
||||
1,
|
||||
|
@ -779,6 +821,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage: Lock = await p2pix.callStatic.mapLocks(
|
||||
1,
|
||||
|
@ -840,6 +883,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
await p2pix
|
||||
.connect(acc01)
|
||||
|
@ -856,6 +900,7 @@ describe("P2PIX", () => {
|
|||
price.add(ethers.constants.One),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage: Lock = await p2pix.callStatic.mapLocks(
|
||||
2,
|
||||
|
@ -906,6 +951,7 @@ describe("P2PIX", () => {
|
|||
newPrice,
|
||||
proof,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage1: Lock = await p2pix.callStatic.mapLocks(
|
||||
1,
|
||||
|
@ -922,6 +968,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage2: Lock = await p2pix.callStatic.mapLocks(
|
||||
2,
|
||||
|
@ -938,6 +985,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const storage3: Lock = await p2pix.callStatic.mapLocks(
|
||||
3,
|
||||
|
@ -1214,6 +1262,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
await mine(13);
|
||||
|
@ -1255,6 +1304,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
await p2pix.release(
|
||||
|
@ -1299,6 +1349,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
await p2pix
|
||||
|
@ -1316,6 +1367,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const fail = p2pix
|
||||
.connect(acc01)
|
||||
|
@ -1357,6 +1409,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const fail = p2pix
|
||||
.connect(acc01)
|
||||
|
@ -1413,6 +1466,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const acc01Key = await p2pix.callStatic._castAddrToKey(
|
||||
acc01.address,
|
||||
|
@ -1577,6 +1631,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
await p2pix
|
||||
.connect(acc03)
|
||||
|
@ -1586,6 +1641,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(50),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
await p2pix
|
||||
.connect(acc03)
|
||||
|
@ -1595,6 +1651,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(25),
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
const lockStatus1 =
|
||||
|
@ -1764,6 +1821,7 @@ describe("P2PIX", () => {
|
|||
ethers.constants.One,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
const fail = p2pix.unlockExpired([lockID]);
|
||||
|
@ -1802,6 +1860,7 @@ describe("P2PIX", () => {
|
|||
ethers.constants.One,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
// await mine(10);
|
||||
|
@ -1835,6 +1894,7 @@ describe("P2PIX", () => {
|
|||
ethers.constants.One,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
await mine(11);
|
||||
|
@ -1898,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.
|
||||
|
@ -1937,6 +1998,7 @@ describe("P2PIX", () => {
|
|||
ethers.BigNumber.from(100),
|
||||
[],
|
||||
[lockID],
|
||||
false
|
||||
);
|
||||
const remaining = await p2pix.callStatic.getBalance(
|
||||
owner.address,
|
||||
|
@ -1970,6 +2032,7 @@ describe("P2PIX", () => {
|
|||
price,
|
||||
proof,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
const lockID = ethers.constants.One;
|
||||
// mine blocks to expire lock
|
||||
|
|
Loading…
Reference in New Issue