Enhanced integration & optimized testing

This commit is contained in:
PedroCailleret 2023-02-14 18:40:02 -03:00
parent 4c8016080d
commit 8310e013f6
40 changed files with 1516 additions and 649 deletions

View File

@ -18,4 +18,6 @@
coverage.json coverage.json
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
contracts/p2pix.sol

View File

@ -32,10 +32,11 @@
## Current Deployment addresses ## Current Deployment addresses
### V1 ### V1
| Testnet | Token Address | P2pix Address |
|--------- |-------------------------------------------- |-------------------------------------------- | | Testnet | Token Address | P2pix Address |
| Goerli | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | | ------- | ------------------------------------------ | ------------------------------------------ |
| Mumbai | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | | Goerli | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 |
| Mumbai | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 |
<!-- All contracts deployed by 0x8dC06F985C131166570825F52447E8c88d64aE20 --> <!-- All contracts deployed by 0x8dC06F985C131166570825F52447E8c88d64aE20 -->
@ -48,10 +49,11 @@
<!-- https://mumbai.polygonscan.com/address/0x5f3EFA9A90532914545CEf527C530658af87e196#code --> <!-- https://mumbai.polygonscan.com/address/0x5f3EFA9A90532914545CEf527C530658af87e196#code -->
### V2 ### V2
| Testnet | Token Address | P2pix Address | Reputation Address |
|--------- |-------------------------------------------- |-------------------------------------------- |-------------------------------------------- | | Testnet | Token Address | P2pix Address | Reputation Address |
| Goerli | 0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00 | 0xefa5cE4351cda51192509cf8De7d8881ADAE95DD | 0x939d3c357dc7017cDbDE681BF8e552b54595318A | | ------- | ------------------------------------------ | ------------------------------------------ | ------------------------------------------ |
| Mumbai | 0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29 | 0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b | 0x1fd30b94f20d2f73e9630261342ba68f244da92b | | Goerli | 0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00 | 0xefa5cE4351cda51192509cf8De7d8881ADAE95DD | 0x939d3c357dc7017cDbDE681BF8e552b54595318A |
| Mumbai | 0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29 | 0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b | 0x1fd30b94f20d2f73e9630261342ba68f244da92b |
<!-- All contracts deployed by 0x8dC06F985C131166570825F52447E8c88d64aE20 --> <!-- All contracts deployed by 0x8dC06F985C131166570825F52447E8c88d64aE20 -->
<!-- https://goerli.etherscan.io/address/0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00#code --> <!-- https://goerli.etherscan.io/address/0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00#code -->
@ -136,7 +138,6 @@ yarn deploy2:localhost
**_NOTE_:** The second script transfers 2M tokens to the first wallet of the node. **_NOTE_:** The second script transfers 2M tokens to the first wallet of the node.
To use the P2Pix smart contract first transfer some of the tokens to other wallets. To use the P2Pix smart contract first transfer some of the tokens to other wallets.
## Deploying to testnets ## Deploying to testnets
Deploy to Ethereum's Goerli testnet: Deploy to Ethereum's Goerli testnet:
@ -151,4 +152,4 @@ Deploy to Polygon's Mumbai testnet:
```sh ```sh
yarn deploy1:mumbai yarn deploy1:mumbai
yarn deploy2:mumbai yarn deploy2:mumbai
``` ```

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -0,0 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json"
}

View File

@ -0,0 +1,116 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "Multicall",
"sourceName": "contracts/lib/utils/Multicall.sol",
"abi": [
{
"inputs": [],
"stateMutability": "payable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "string",
"name": "reason",
"type": "string"
}
],
"name": "CallFailed",
"type": "error"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "target",
"type": "address"
},
{
"internalType": "bytes",
"name": "callData",
"type": "bytes"
}
],
"internalType": "struct Multicall.Call[]",
"name": "calls",
"type": "tuple[]"
}
],
"name": "mtc1",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "bytes[]",
"name": "",
"type": "bytes[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "target",
"type": "address"
},
{
"internalType": "bytes",
"name": "callData",
"type": "bytes"
}
],
"internalType": "struct Multicall.Call[]",
"name": "calls",
"type": "tuple[]"
}
],
"name": "mtc2",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
},
{
"components": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
},
{
"internalType": "bytes",
"name": "returnData",
"type": "bytes"
}
],
"internalType": "struct Multicall.Result[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": "0x60806040526108ec806100136000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a",
"linkReferences": {},
"deployedLinkReferences": {}
}

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" "buildInfo": "../../../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json"
} }

View File

@ -1,4 +1,4 @@
{ {
"_format": "hh-sol-dbg-1", "_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/4a149f14ea0fec7293fb79d89ccb9fe7.json" "buildInfo": "../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json"
} }

File diff suppressed because one or more lines are too long

View File

@ -2,18 +2,6 @@
pragma solidity 0.8.9; pragma solidity 0.8.9;
library DataTypes { library DataTypes {
// struct Deposit {
// /// @dev Remaining tokens available.
// uint256 remaining;
// /// @dev The PIX account for the seller receive transactions.
// string pixTarget;
// address seller;
// /// @dev ERC20 stable token address.
// address token;
// /// @dev Could be invalidated by the seller.
// bool valid;
// }
struct Lock { struct Lock {
uint256 sellerKey; uint256 sellerKey;
uint256 counter; uint256 counter;
@ -33,4 +21,12 @@ library DataTypes {
address relayerAddress; address relayerAddress;
address token; address token;
} }
// prettier-ignore
enum LockStatus {
Inexistent, // 0 := Uninitialized Lock.
Active, // 1 := Valid Lock.
Expired, // 2 := Expired Lock.
Released // 3 := Already released Lock.
}
} }

View File

@ -0,0 +1,80 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
/// @title Multicall.
/// @notice Contract that batches view function calls and aggregates their results.
/// @author Adapted from Makerdao's Multicall2 (https://github.com/makerdao/multicall/blob/master/src/Multicall2.sol).
contract Multicall {
/// @dev 0x
error CallFailed(string reason);
struct Call {
address target;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
//prettier-ignore
constructor(/* */) payable {/* */}
function mtc1(Call[] calldata calls)
external
returns (uint256, bytes[] memory)
{
uint256 bn = block.number;
uint256 len = calls.length;
bytes[] memory res = new bytes[](len);
uint256 j;
while (j < len) {
(bool success, bytes memory ret) = calls[j]
.target
.call(calls[j].callData);
if (!success) {
if (ret.length < 0x44) revert CallFailed("");
assembly {
ret := add(ret, 0x04)
}
revert CallFailed({
reason: abi.decode(ret, (string))
});
}
res[j] = ret;
++j;
}
return (bn, res);
}
function mtc2(Call[] calldata calls)
external
returns (
uint256,
bytes32,
Result[] memory
)
{
uint256 bn = block.number;
// µ 0 s [0] P(IHp , µs [0], 0) P is the hash of a block of a particular number, up to a maximum age.
// 0 is left on the stack if the looked for `block.number` is >= to the current `block.number` or more than 256
// blocks behind the current block (Yellow Paper, p. 33, https://ethereum.github.io/yellowpaper/paper.pdf).
bytes32 bh = blockhash(
bn /* - 1 */
);
uint256 len = calls.length;
Result[] memory res = new Result[](len);
uint256 i;
for (i; i < len; ) {
(bool success, bytes memory ret) = calls[i]
.target
.call(calls[i].callData);
res[i] = Result(success, ret);
++i;
}
return (bn, bh, res);
}
}

View File

@ -114,46 +114,4 @@ library SafeTransferLib {
require(success, "TRANSFER_FAILED"); require(success, "TRANSFER_FAILED");
} }
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
// We'll write our calldata to this slot below, but restore it later.
let memPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(
0,
0x095ea7b300000000000000000000000000000000000000000000000000000000
)
mstore(4, to) // Append the "to" argument.
mstore(36, amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(
and(
eq(mload(0), 1),
gt(returndatasize(), 31)
),
iszero(returndatasize())
),
// We use 68 because that's the total length of our calldata (4 + 32 * 2)
// Counterintuitively, this call() must be positioned after the or() in the
// surrounding and() because and() evaluates its arguments from right to left.
call(gas(), token, 0, 0, 68, 0, 32)
)
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, memPointer) // Restore the memPointer.
}
require(success, "APPROVE_FAILED");
}
} }

View File

@ -26,6 +26,7 @@ contract P2PIX is
// solhint-disable no-empty-blocks // solhint-disable no-empty-blocks
using DT for DT.Lock; using DT for DT.Lock;
using DT for DT.LockStatus;
/// Constants /// Constants
@ -105,15 +106,11 @@ contract P2PIX is
ERC20 t = ERC20(_token); ERC20 t = ERC20(_token);
uint256 k = _castAddrToKey(msg.sender); uint256 k = _castAddrToKey(msg.sender);
if (_pixTarget == 0) if (_pixTarget == 0) revert EmptyPixTarget();
revert EmptyPixTarget(); if (!allowedERC20s[t]) revert TokenDenied();
if (!allowedERC20s[t]) uint256 _sellerBalance = sellerBalance[k][t];
revert TokenDenied();
uint256 _sellerBalance =
sellerBalance[k][t];
uint256 currBal = uint256 currBal = _sellerBalance & BITMASK_SB_ENTRY;
_sellerBalance & BITMASK_SB_ENTRY;
if ((currBal + _amount) > 1e8 ether) if ((currBal + _amount) > 1e8 ether)
revert MaxBalExceeded(); revert MaxBalExceeded();
@ -130,12 +127,8 @@ contract P2PIX is
amountCasted, amountCasted,
pixTargetCasted, pixTargetCasted,
validCasted validCasted
) = _castToUint( ) = _castToUint(_amount, _pixTarget, _valid);
_amount,
_pixTarget,
_valid
);
sellerBalance[k][t] = sellerBalance[k][t] =
(currBal + amountCasted) | (currBal + amountCasted) |
(pixTargetCasted << BITPOS_PIXTARGET) | (pixTargetCasted << BITPOS_PIXTARGET) |
@ -150,11 +143,7 @@ contract P2PIX is
clearReentrancyGuard(); clearReentrancyGuard();
emit DepositAdded( emit DepositAdded(msg.sender, _token, _amount);
msg.sender,
_token,
_amount
);
} }
/// @notice Enables seller to invalidate future /// @notice Enables seller to invalidate future
@ -162,29 +151,23 @@ contract P2PIX is
/// @dev This function does not affect any ongoing active locks. /// @dev This function does not affect any ongoing active locks.
/// @dev Function sighash: 0x72fada5c. /// @dev Function sighash: 0x72fada5c.
function setValidState(ERC20 token, bool state) public { function setValidState(ERC20 token, bool state) public {
uint256 key = uint256 key = _castAddrToKey(msg.sender);
_castAddrToKey(msg.sender); uint256 _sellerBalance = sellerBalance[key][token];
uint256 _sellerBalance =
sellerBalance[key][token];
if (_sellerBalance != 0) { if (_sellerBalance != 0) {
uint256 _valid; uint256 _valid;
assembly { _valid := state } assembly {
_valid := state
}
_sellerBalance = _sellerBalance =
(_sellerBalance & BITMASK_VALID) | (_sellerBalance & BITMASK_VALID) |
(_valid << BITPOS_VALID); (_valid << BITPOS_VALID);
sellerBalance[key][token] =
_sellerBalance;
emit ValidSet( sellerBalance[key][token] = _sellerBalance;
msg.sender,
address(token), emit ValidSet(msg.sender, address(token), state);
state } else revert NotInitialized();
);
} else
revert NotInitialized();
} }
/// @notice Public method designed to lock an remaining amount of /// @notice Public method designed to lock an remaining amount of
@ -219,33 +202,26 @@ contract P2PIX is
unlockExpired(expiredLocks); unlockExpired(expiredLocks);
ERC20 t = ERC20(_token); ERC20 t = ERC20(_token);
if (!getValid(_seller, t)) if (!getValid(_seller, t)) revert InvalidDeposit();
revert InvalidDeposit();
uint256 bal = uint256 bal = getBalance(_seller, t);
getBalance(_seller, t); if (bal < _amount) revert NotEnoughTokens();
if (bal < _amount)
revert NotEnoughTokens();
uint256 k = uint256 k = _castAddrToKey(_seller);
_castAddrToKey(_seller);
uint256 cCounter = uint256 cCounter = lockCounter + 1;
lockCounter + 1;
if (mapLocks[cCounter].expirationBlock if (
>= block.number) mapLocks[cCounter].expirationBlock >= block.number
revert NotExpired(); ) revert NotExpired();
DT.Lock memory l = DT.Lock( DT.Lock memory l = DT.Lock(
k, k,
cCounter, cCounter,
_relayerPremium, _relayerPremium,
_amount, _amount,
(block.number + (block.number + defaultLockBlocks),
defaultLockBlocks), uint160(sellerBalance[k][t] >> BITPOS_PIXTARGET),
uint160(sellerBalance[k][t]
>> BITPOS_PIXTARGET),
_buyerAddress, _buyerAddress,
_relayerTarget, _relayerTarget,
msg.sender, msg.sender,
@ -259,58 +235,34 @@ contract P2PIX is
msg.sender msg.sender
); );
_addLock( _addLock(bal, _amount, cCounter, l, t, k);
bal,
_amount,
cCounter,
l,
t,
k
);
lockCounter++; lockCounter++;
// Halt execution and output `lockID`. // Halt execution and output `lockID`.
return cCounter; return cCounter;
} else { } else {
if (l.amount <= 1e2 ether) { if (l.amount <= 1e2 ether) {
_addLock( _addLock(bal, _amount, cCounter, l, t, k);
bal,
_amount,
cCounter,
l,
t,
k
);
lockCounter++; lockCounter++;
// Halt execution and output `lockID`. // Halt execution and output `lockID`.
return cCounter; return cCounter;
} else { } else {
uint256 userCredit = userRecord[ uint256 userCredit = userRecord[
_castAddrToKey(msg.sender) _castAddrToKey(msg.sender)
]; ];
uint256 spendLimit; uint256 spendLimit;
(spendLimit) = (spendLimit) = _limiter(userCredit / WAD);
_limiter(userCredit / WAD);
if ( if (
l.amount > (spendLimit * WAD) || l.amount > (spendLimit * WAD) ||
l.amount > 1e6 ether l.amount > 1e6 ether
) revert AmountNotAllowed(); ) revert AmountNotAllowed();
_addLock( _addLock(bal, _amount, cCounter, l, t, k);
bal,
_amount,
cCounter,
l,
t,
k
);
lockCounter++; lockCounter++;
@ -374,25 +326,22 @@ contract P2PIX is
ERC20 t = ERC20(l.token); ERC20 t = ERC20(l.token);
// We cache values before zeroing them out. // We cache values before zeroing them out.
uint256 lockAmount = uint256 lockAmount = l.amount;
l.amount; uint256 totalAmount = (lockAmount - l.relayerPremium);
uint256 totalAmount =
(lockAmount - l.relayerPremium);
l.amount = 0; l.amount = 0;
l.expirationBlock = 0; l.expirationBlock = 0;
usedTransactions[message] = true; usedTransactions[message] = true;
if (msg.sender != l.relayerAddress) { if (msg.sender != l.relayerAddress) {
userRecord[ userRecord[_castAddrToKey(msg.sender)] += l
_castAddrToKey(msg.sender) .relayerPremium;
] += l.relayerPremium;
userRecord[ userRecord[
_castAddrToKey(l.relayerAddress) _castAddrToKey(l.relayerAddress)
] += lockAmount; ] += lockAmount;
} else { } else {
userRecord[_castAddrToKey(msg.sender)] userRecord[_castAddrToKey(msg.sender)] += (l
+= (l.relayerPremium + lockAmount); .relayerPremium + lockAmount);
} }
SafeTransferLib.safeTransfer( SafeTransferLib.safeTransfer(
@ -423,11 +372,7 @@ contract P2PIX is
} }
} }
emit LockReleased( emit LockReleased(l.buyerAddress, lockID, lockAmount);
l.buyerAddress,
lockID,
lockAmount
);
} }
/// @notice Unlocks expired locks. /// @notice Unlocks expired locks.
@ -443,42 +388,34 @@ contract P2PIX is
uint256 locksSize = lockIDs.length; uint256 locksSize = lockIDs.length;
for (i; i < locksSize; ) { for (i; i < locksSize; ) {
DT.Lock storage l = DT.Lock storage l = mapLocks[lockIDs[i]];
mapLocks[lockIDs[i]];
_notExpired(l); _notExpired(l);
uint256 _sellerBalance = uint256 _sellerBalance = sellerBalance[
sellerBalance[ l.sellerKey
l.sellerKey][ERC20(l.token) ][ERC20(l.token)] & BITMASK_SB_ENTRY;
] & BITMASK_SB_ENTRY;
if ((_sellerBalance + l.amount) > 1e8 ether)
if (
(_sellerBalance + l.amount)
> 1e8 ether
)
revert MaxBalExceeded(); revert MaxBalExceeded();
sellerBalance[ sellerBalance[l.sellerKey][ERC20(l.token)] += l
l.sellerKey][ERC20(l.token) .amount;
] += l.amount;
l.amount = 0; l.amount = 0;
uint256 userKey = uint256 userKey = _castAddrToKey(
_castAddrToKey(l.relayerAddress); l.relayerAddress
uint256 _newUserRecord = );
(userRecord[userKey] >> 1); uint256 _newUserRecord = (userRecord[userKey] >>
1);
if (_newUserRecord <= 1e2 ether) { if (_newUserRecord <= 1e2 ether) {
userRecord[userKey] = 1e2 ether; userRecord[userKey] = 1e2 ether;
} else { } else {
userRecord[userKey] = _newUserRecord; userRecord[userKey] = _newUserRecord;
} }
emit LockReturned( emit LockReturned(l.buyerAddress, lockIDs[i]);
l.buyerAddress,
lockIDs[i]
);
unchecked { unchecked {
++i; ++i;
@ -502,23 +439,16 @@ contract P2PIX is
ERC20 token, ERC20 token,
uint256 amount, uint256 amount,
uint256[] calldata expiredLocks uint256[] calldata expiredLocks
) ) public nonReentrant {
public
nonReentrant
{
unlockExpired(expiredLocks); unlockExpired(expiredLocks);
if (getValid(msg.sender, token) if (getValid(msg.sender, token) == true) {
== true
) {
setValidState(token, false); setValidState(token, false);
} }
uint256 key = uint256 key = _castAddrToKey(msg.sender);
_castAddrToKey(msg.sender);
_decBal( _decBal(
(sellerBalance[key][token] (sellerBalance[key][token] & BITMASK_SB_ENTRY),
& BITMASK_SB_ENTRY),
amount, amount,
token, token,
key key
@ -784,17 +714,23 @@ contract P2PIX is
// sellerBalance[_castAddrToKey(seller)][token] & // sellerBalance[_castAddrToKey(seller)][token] &
// BITMASK_SB_ENTRY; // BITMASK_SB_ENTRY;
assembly { assembly {
for {/* */} iszero(0x0) {/* */} { for {
mstore(0x00, shl(0xC,seller)) /* */
mstore(0x20, sellerBalance.slot) } iszero(0x0) {
let sbkslot := keccak256(0x00, 0x40) /* */
mstore(0x00, token) } {
mstore(0x20, sbkslot) mstore(0x00, shl(0xC, seller))
bal := and( mstore(0x20, sellerBalance.slot)
BITMASK_SB_ENTRY, let sbkslot := keccak256(0x00, 0x40)
sload(keccak256(0x00,0x40) mstore(0x00, token)
)) break mstore(0x20, sbkslot)
}} bal := and(
BITMASK_SB_ENTRY,
sload(keccak256(0x00, 0x40))
)
break
}
}
} }
function getValid(address seller, ERC20 token) function getValid(address seller, ERC20 token)
@ -807,19 +743,26 @@ contract P2PIX is
// ][token]; // ][token];
// ] >> BITPOS_VALID) & BITMASK_SB_ENTRY; // ] >> BITPOS_VALID) & BITMASK_SB_ENTRY;
assembly { assembly {
for {/* */} iszero(0x0) {/* */} { for {
mstore(0x00, shl(0xC,seller)) /* */
mstore(0x20, sellerBalance.slot) } iszero(0x0) {
let sbkslot := keccak256(0x00, 0x40) /* */
mstore(0x00, token) } {
mstore(0x20, sbkslot) mstore(0x00, shl(0xC, seller))
valid := and( mstore(0x20, sellerBalance.slot)
BITMASK_SB_ENTRY, let sbkslot := keccak256(0x00, 0x40)
shr( mstore(0x00, token)
BITPOS_VALID, mstore(0x20, sbkslot)
sload(keccak256(0x00,0x40) valid := and(
))) break BITMASK_SB_ENTRY,
}} shr(
BITPOS_VALID,
sload(keccak256(0x00, 0x40))
)
)
break
}
}
} }
function getPixTarget(address seller, ERC20 token) function getPixTarget(address seller, ERC20 token)
@ -832,40 +775,38 @@ contract P2PIX is
// BITPOS_PIXTARGET // BITPOS_PIXTARGET
// ); // );
assembly { assembly {
for {/* */} iszero(0) {/* */} { for {
mstore(0,shl(12,seller)) /* */
mstore(32,sellerBalance.slot) } iszero(0) {
let sbkslot := keccak256(0,64) /* */
mstore(0,token) } {
mstore(32,sbkslot) mstore(0, shl(12, seller))
pixTarget := shr( mstore(32, sellerBalance.slot)
BITPOS_PIXTARGET, let sbkslot := keccak256(0, 64)
sload(keccak256(0,64) mstore(0, token)
)) break mstore(32, sbkslot)
}} pixTarget := shr(
BITPOS_PIXTARGET,
sload(keccak256(0, 64))
)
break
}
}
} }
function getBalances( function getBalances(
address[] memory sellers, address[] memory sellers,
ERC20 token ERC20 token
) ) external view returns (uint256[] memory) {
external
view
returns(uint256[] memory)
{
uint256 j; uint256 j;
uint256 len = uint256 len = sellers.length;
sellers.length; uint256[] memory balances = new uint256[](len);
uint256[] memory balances =
new uint256[](len);
while (j < len) { while (j < len) {
uint256 bal = uint256 bal = getBalance(sellers[j], token);
getBalance(
sellers[j],
token
);
balances[j] = bal; balances[j] = bal;
unchecked { ++j; } unchecked {
++j;
}
} }
return balances; return balances;
@ -875,42 +816,51 @@ contract P2PIX is
/// @dev Call will not revert if provided with an empty array as parameter. /// @dev Call will not revert if provided with an empty array as parameter.
/// @dev Function sighash: 0x49ef8448 /// @dev Function sighash: 0x49ef8448
function getLocksStatus(uint256[] memory ids) function getLocksStatus(uint256[] memory ids)
external external
view view
returns( returns (uint256[] memory, DT.LockStatus[] memory)
uint256[] memory, {
bool[] memory if (ids.length == 0) {
) { uint256[] memory null1 = new uint256[](0);
if (ids.length == 0) { DT.LockStatus[]
uint256[] memory null1 = memory null2 = new DT.LockStatus[](0);
new uint256[](0); return (null1, null2);
bool[] memory null2 =
new bool[](0);
return(null1, null2); }
uint256 c;
uint256 len =
ids.length;
bool[] memory status =
new bool[](len);
uint256[] memory sortedIDs =
new uint256[](len);
for(c; c < len;) {
if(
mapLocks[ids[c]].expirationBlock
< block.number ||
mapLocks[ids[c]].amount == 0x0) {
sortedIDs[c] = ids[c];
status[c] = false; ++c;
} else {
sortedIDs[c] = ids[c];
status[c] = true; ++c;
}
}
return(sortedIDs, status);
} }
uint256 c;
uint256 len = ids.length;
uint256[] memory sortedIDs = new uint256[](len);
DT.LockStatus[] memory status = new DT.LockStatus[](
len
);
unchecked {
for (c; c < len; ) {
if (mapLocks[ids[c]].sellerKey == 0x0) {
sortedIDs[c] = ids[c];
status[c] = type(DT.LockStatus).min;
++c;
} else if (mapLocks[ids[c]].amount == 0x0) {
sortedIDs[c] = ids[c];
status[c] = type(DT.LockStatus).max;
++c;
} else if (
mapLocks[ids[c]].expirationBlock <
block.number
) {
sortedIDs[c] = ids[c];
status[c] = DT.LockStatus.Expired;
++c;
} else {
sortedIDs[c] = ids[c];
status[c] = DT.LockStatus.Active;
++c;
}
}
}
return (sortedIDs, status);
}
/// @notice Public method that handles `address` /// @notice Public method that handles `address`
/// to `uint256` safe type casting. /// to `uint256` safe type casting.
/// @dev Function sighash: 0x4b2ae980. /// @dev Function sighash: 0x4b2ae980.
@ -921,7 +871,7 @@ contract P2PIX is
{ {
// _key = uint256(uint160(address(_addr))) << 12; // _key = uint256(uint160(address(_addr))) << 12;
assembly { assembly {
_key := shl(12,_addr) _key := shl(12, _addr)
} }
} }
@ -932,7 +882,7 @@ contract P2PIX is
{ {
// _addr = address(uint160(uint256(_key >> 12))); // _addr = address(uint160(uint256(_key >> 12)));
assembly { assembly {
_addr := shr(12,_key) _addr := shr(12, _key)
} }
} }
} }

View File

@ -5,4 +5,4 @@
], ],
"p2pix": "0xefa5cE4351cda51192509cf8De7d8881ADAE95DD", "p2pix": "0xefa5cE4351cda51192509cf8De7d8881ADAE95DD",
"token": "0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00" "token": "0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00"
} }

View File

@ -5,4 +5,4 @@
], ],
"p2pix": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29", "p2pix": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29",
"token": "0xD38D6367f452D097ccBfDe4490b7de570B6A72Db" "token": "0xD38D6367f452D097ccBfDe4490b7de570B6A72Db"
} }

View File

@ -5,4 +5,4 @@
], ],
"p2pix": "0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b", "p2pix": "0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b",
"token": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29" "token": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29"
} }

View File

@ -34,7 +34,7 @@ const chainIds = {
hardhat: 31337, hardhat: 31337,
mainnet: 1, mainnet: 1,
sepolia: 11155111, sepolia: 11155111,
goerli : 5, goerli: 5,
"polygon-mumbai": 80001, "polygon-mumbai": 80001,
}; };
@ -44,8 +44,10 @@ function getChainConfig(
let jsonRpcUrl: string; let jsonRpcUrl: string;
switch (chain) { switch (chain) {
case "polygon-mumbai": case "polygon-mumbai":
jsonRpcUrl = "https://polygon-mumbai.g.alchemy.com/v2/" + alchemyApiKey; jsonRpcUrl =
break; "https://polygon-mumbai.g.alchemy.com/v2/" +
alchemyApiKey;
break;
default: default:
jsonRpcUrl = jsonRpcUrl =
"https://" + chain + ".infura.io/v3/" + infuraApiKey; "https://" + chain + ".infura.io/v3/" + infuraApiKey;
@ -138,4 +140,4 @@ const config: HardhatUserConfig = {
}, },
}; };
export default config; export default config;

View File

@ -64,7 +64,7 @@
"fs-extra": "^10.1.0", "fs-extra": "^10.1.0",
"hardhat": "^2.12.2", "hardhat": "^2.12.2",
"hardhat-gas-reporter": "^1.0.9", "hardhat-gas-reporter": "^1.0.9",
"hardhat-tracer": "^1.2.0", "hardhat-tracer": "beta",
"husky": "^8.0.1", "husky": "^8.0.1",
"keccak256": "^1.0.6", "keccak256": "^1.0.6",
"lint-staged": "^13.0.3", "lint-staged": "^13.0.3",

View File

@ -3,11 +3,10 @@ import "@nomiclabs/hardhat-etherscan";
import { BigNumber } from "ethers"; import { BigNumber } from "ethers";
import * as fs from "fs"; import * as fs from "fs";
import { ethers, network } from "hardhat"; import { ethers, network } from "hardhat";
import hre from "hardhat";
import { Deploys } from "../test/utils/fixtures"; import { Deploys } from "../test/utils/fixtures";
import hre from "hardhat";
let deploysJson: Deploys; let deploysJson: Deploys;
const supply: BigNumber = ethers.utils.parseEther("20000000"); const supply: BigNumber = ethers.utils.parseEther("20000000");
@ -54,4 +53,4 @@ main()
.catch(error => { .catch(error => {
console.log(error); console.log(error);
process.exit(1); process.exit(1);
}); });

View File

@ -2,11 +2,10 @@ 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 hre from "hardhat";
import { Deploys } from "../test/utils/fixtures"; import { Deploys } from "../test/utils/fixtures";
import hre from "hardhat";
let deploysJson: Deploys; let deploysJson: Deploys;
const main = async () => { const main = async () => {
@ -53,10 +52,9 @@ const main = async () => {
//verify //verify
await hre.run("verify:verify", { await hre.run("verify:verify", {
address: p2pix.address, address: p2pix.address,
constructorArguments: constructorArguments: [
[ 10,
10, deploysJson.signers,
deploysJson.signers,
reputation.address, reputation.address,
[deploysJson.token], [deploysJson.token],
[true], [true],
@ -73,4 +71,4 @@ main()
.catch(error => { .catch(error => {
console.log(error); console.log(error);
process.exit(1); process.exit(1);
}); });

View File

@ -0,0 +1,174 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import {
Signer,
utils,
Contract,
ContractFactory,
PayableOverrides,
} from "ethers";
import type { Provider, TransactionRequest } from "@ethersproject/providers";
import type { PromiseOrValue } from "../../../common";
import type {
Multicall,
MulticallInterface,
} from "../../../lib/utils/Multicall";
const _abi = [
{
inputs: [],
stateMutability: "payable",
type: "constructor",
},
{
inputs: [
{
internalType: "string",
name: "reason",
type: "string",
},
],
name: "CallFailed",
type: "error",
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address",
},
{
internalType: "bytes",
name: "callData",
type: "bytes",
},
],
internalType: "struct Multicall.Call[]",
name: "calls",
type: "tuple[]",
},
],
name: "mtc1",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
{
internalType: "bytes[]",
name: "",
type: "bytes[]",
},
],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [
{
components: [
{
internalType: "address",
name: "target",
type: "address",
},
{
internalType: "bytes",
name: "callData",
type: "bytes",
},
],
internalType: "struct Multicall.Call[]",
name: "calls",
type: "tuple[]",
},
],
name: "mtc2",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
{
internalType: "bytes32",
name: "",
type: "bytes32",
},
{
components: [
{
internalType: "bool",
name: "success",
type: "bool",
},
{
internalType: "bytes",
name: "returnData",
type: "bytes",
},
],
internalType: "struct Multicall.Result[]",
name: "",
type: "tuple[]",
},
],
stateMutability: "nonpayable",
type: "function",
},
];
const _bytecode =
"0x60806040526108ec806100136000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a";
type MulticallConstructorParams =
| [signer?: Signer]
| ConstructorParameters<typeof ContractFactory>;
const isSuperArgs = (
xs: MulticallConstructorParams
): xs is ConstructorParameters<typeof ContractFactory> => xs.length > 1;
export class Multicall__factory extends ContractFactory {
constructor(...args: MulticallConstructorParams) {
if (isSuperArgs(args)) {
super(...args);
} else {
super(_abi, _bytecode, args[0]);
}
}
override deploy(
overrides?: PayableOverrides & { from?: PromiseOrValue<string> }
): Promise<Multicall> {
return super.deploy(overrides || {}) as Promise<Multicall>;
}
override getDeployTransaction(
overrides?: PayableOverrides & { from?: PromiseOrValue<string> }
): TransactionRequest {
return super.getDeployTransaction(overrides || {});
}
override attach(address: string): Multicall {
return super.attach(address) as Multicall;
}
override connect(signer: Signer): Multicall__factory {
return super.connect(signer) as Multicall__factory;
}
static readonly bytecode = _bytecode;
static readonly abi = _abi;
static createInterface(): MulticallInterface {
return new utils.Interface(_abi) as MulticallInterface;
}
static connect(
address: string,
signerOrProvider: Signer | Provider
): Multicall {
return new Contract(address, _abi, signerOrProvider) as Multicall;
}
}

View File

@ -1,4 +1,5 @@
/* Autogenerated file. Do not edit manually. */ /* Autogenerated file. Do not edit manually. */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export { Multicall__factory } from "./Multicall__factory";
export { ReentrancyGuard__factory } from "./ReentrancyGuard__factory"; export { ReentrancyGuard__factory } from "./ReentrancyGuard__factory";

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,10 @@ declare module "hardhat/types/runtime" {
name: "ERC20", name: "ERC20",
signerOrOptions?: ethers.Signer | FactoryOptions signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.ERC20__factory>; ): Promise<Contracts.ERC20__factory>;
getContractFactory(
name: "Multicall",
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.Multicall__factory>;
getContractFactory( getContractFactory(
name: "ReentrancyGuard", name: "ReentrancyGuard",
signerOrOptions?: ethers.Signer | FactoryOptions signerOrOptions?: ethers.Signer | FactoryOptions
@ -70,6 +74,11 @@ declare module "hardhat/types/runtime" {
address: string, address: string,
signer?: ethers.Signer signer?: ethers.Signer
): Promise<Contracts.ERC20>; ): Promise<Contracts.ERC20>;
getContractAt(
name: "Multicall",
address: string,
signer?: ethers.Signer
): Promise<Contracts.Multicall>;
getContractAt( getContractAt(
name: "ReentrancyGuard", name: "ReentrancyGuard",
address: string, address: string,

View File

@ -17,6 +17,8 @@ export type { MockToken } from "./lib/mock/mockToken.sol/MockToken";
export { MockToken__factory } from "./factories/lib/mock/mockToken.sol/MockToken__factory"; export { MockToken__factory } from "./factories/lib/mock/mockToken.sol/MockToken__factory";
export type { ERC20 } from "./lib/tokens/ERC20"; export type { ERC20 } from "./lib/tokens/ERC20";
export { ERC20__factory } from "./factories/lib/tokens/ERC20__factory"; export { ERC20__factory } from "./factories/lib/tokens/ERC20__factory";
export type { Multicall } from "./lib/utils/Multicall";
export { Multicall__factory } from "./factories/lib/utils/Multicall__factory";
export type { ReentrancyGuard } from "./lib/utils/ReentrancyGuard"; export type { ReentrancyGuard } from "./lib/utils/ReentrancyGuard";
export { ReentrancyGuard__factory } from "./factories/lib/utils/ReentrancyGuard__factory"; export { ReentrancyGuard__factory } from "./factories/lib/utils/ReentrancyGuard__factory";
export type { P2PIX } from "./p2pix.sol/P2PIX"; export type { P2PIX } from "./p2pix.sol/P2PIX";

View File

@ -0,0 +1,155 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
BaseContract,
BigNumber,
BytesLike,
CallOverrides,
ContractTransaction,
Overrides,
PopulatedTransaction,
Signer,
utils,
} from "ethers";
import type { FunctionFragment, Result } from "@ethersproject/abi";
import type { Listener, Provider } from "@ethersproject/providers";
import type {
TypedEventFilter,
TypedEvent,
TypedListener,
OnEvent,
PromiseOrValue,
} from "../../common";
export declare namespace Multicall {
export type CallStruct = {
target: PromiseOrValue<string>;
callData: PromiseOrValue<BytesLike>;
};
export type CallStructOutput = [string, string] & {
target: string;
callData: string;
};
export type ResultStruct = {
success: PromiseOrValue<boolean>;
returnData: PromiseOrValue<BytesLike>;
};
export type ResultStructOutput = [boolean, string] & {
success: boolean;
returnData: string;
};
}
export interface MulticallInterface extends utils.Interface {
functions: {
"mtc1((address,bytes)[])": FunctionFragment;
"mtc2((address,bytes)[])": FunctionFragment;
};
getFunction(nameOrSignatureOrTopic: "mtc1" | "mtc2"): FunctionFragment;
encodeFunctionData(
functionFragment: "mtc1",
values: [Multicall.CallStruct[]]
): string;
encodeFunctionData(
functionFragment: "mtc2",
values: [Multicall.CallStruct[]]
): string;
decodeFunctionResult(functionFragment: "mtc1", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "mtc2", data: BytesLike): Result;
events: {};
}
export interface Multicall extends BaseContract {
connect(signerOrProvider: Signer | Provider | string): this;
attach(addressOrName: string): this;
deployed(): Promise<this>;
interface: MulticallInterface;
queryFilter<TEvent extends TypedEvent>(
event: TypedEventFilter<TEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TEvent>>;
listeners<TEvent extends TypedEvent>(
eventFilter?: TypedEventFilter<TEvent>
): Array<TypedListener<TEvent>>;
listeners(eventName?: string): Array<Listener>;
removeAllListeners<TEvent extends TypedEvent>(
eventFilter: TypedEventFilter<TEvent>
): this;
removeAllListeners(eventName?: string): this;
off: OnEvent<this>;
on: OnEvent<this>;
once: OnEvent<this>;
removeListener: OnEvent<this>;
functions: {
mtc1(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
mtc2(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
};
mtc1(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
mtc2(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;
callStatic: {
mtc1(
calls: Multicall.CallStruct[],
overrides?: CallOverrides
): Promise<[BigNumber, string[]]>;
mtc2(
calls: Multicall.CallStruct[],
overrides?: CallOverrides
): Promise<[BigNumber, string, Multicall.ResultStructOutput[]]>;
};
filters: {};
estimateGas: {
mtc1(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;
mtc2(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;
};
populateTransaction: {
mtc1(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;
mtc2(
calls: Multicall.CallStruct[],
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;
};
}

View File

@ -1,4 +1,5 @@
/* Autogenerated file. Do not edit manually. */ /* Autogenerated file. Do not edit manually. */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export type { Multicall } from "./Multicall";
export type { ReentrancyGuard } from "./ReentrancyGuard"; export type { ReentrancyGuard } from "./ReentrancyGuard";

View File

@ -590,7 +590,7 @@ export interface P2PIX extends BaseContract {
getLocksStatus( getLocksStatus(
ids: PromiseOrValue<BigNumberish>[], ids: PromiseOrValue<BigNumberish>[],
overrides?: CallOverrides overrides?: CallOverrides
): Promise<[BigNumber[], boolean[]]>; ): Promise<[BigNumber[], number[]]>;
getPixTarget( getPixTarget(
seller: PromiseOrValue<string>, seller: PromiseOrValue<string>,
@ -785,7 +785,7 @@ export interface P2PIX extends BaseContract {
getLocksStatus( getLocksStatus(
ids: PromiseOrValue<BigNumberish>[], ids: PromiseOrValue<BigNumberish>[],
overrides?: CallOverrides overrides?: CallOverrides
): Promise<[BigNumber[], boolean[]]>; ): Promise<[BigNumber[], number[]]>;
getPixTarget( getPixTarget(
seller: PromiseOrValue<string>, seller: PromiseOrValue<string>,
@ -980,7 +980,7 @@ export interface P2PIX extends BaseContract {
getLocksStatus( getLocksStatus(
ids: PromiseOrValue<BigNumberish>[], ids: PromiseOrValue<BigNumberish>[],
overrides?: CallOverrides overrides?: CallOverrides
): Promise<[BigNumber[], boolean[]]>; ): Promise<[BigNumber[], number[]]>;
getPixTarget( getPixTarget(
seller: PromiseOrValue<string>, seller: PromiseOrValue<string>,

View File

@ -23,19 +23,73 @@ describe("Reputation", () => {
({ reputation } = await loadFixture(repFixture)); ({ reputation } = await loadFixture(repFixture));
}); });
// describe("Limiter", async () => {
// it("Curve reliability", async () => {
// const tx1 = await reputation.connect(owner).limiter(0);
// const tx2 = await reputation.limiter(500);
// const tx3 = await reputation
// .connect(owner)
// .limiter(444444);
// const tx4 = await reputation.limiter(988700);
// expect(tx1).to.eq(curve(0));
// expect(tx2).to.eq(curve(500));
// expect(tx3).to.eq(curve(444444));
// expect(tx4).to.eq(curve(988700));
// });
// });
describe("Limiter", async () => { describe("Limiter", async () => {
it("Curve reliability", async () => { it("Curve reliability", async () => {
const tx1 = await reputation.connect(owner).limiter(0); const testCases = [
const tx2 = await reputation.limiter(500); {
const tx3 = await reputation x: 0,
.connect(owner) expected: curve(0),
.limiter(444444); },
const tx4 = await reputation.limiter(988700); {
x: 500,
expected: curve(500),
},
{
x: 444444,
expected: curve(444444),
},
{
x: 988700,
expected: curve(988700),
},
{
x: Number.MAX_SAFE_INTEGER,
shouldRevert: "overflow",
},
{
x: Number.POSITIVE_INFINITY,
shouldRevert: "overflow",
},
{
x: Number.NEGATIVE_INFINITY,
shouldRevert: "overflow",
},
{
x: -1,
shouldRevert: "value out-of-bounds",
},
{
x: Number.NaN,
shouldRevert: "invalid BigNumber string",
},
];
expect(tx1).to.eq(curve(0)); for (const testCase of testCases) {
expect(tx2).to.eq(curve(500)); if (testCase.shouldRevert != undefined) {
expect(tx3).to.eq(curve(444444)); await expect(reputation.limiter(testCase.x)).to.be
expect(tx4).to.eq(curve(988700)); .rejected;
} else {
const result = await reputation.limiter(testCase.x);
expect(result).to.eq(testCase.expected).and.to.be
.ok;
}
}
}); });
}); });
}); });

File diff suppressed because it is too large Load Diff

View File

@ -19,4 +19,5 @@ export enum P2PixErrors {
MaxBalExceeded = "MaxBalExceeded", MaxBalExceeded = "MaxBalExceeded",
NotInitialized = "NotInitialized", NotInitialized = "NotInitialized",
DecOverflow = "DecOverflow", DecOverflow = "DecOverflow",
CallFailed = "CallFailed",
} }

View File

@ -6,7 +6,9 @@ import { MerkleTree } from "merkletreejs";
import { import {
MockToken, MockToken,
Multicall,
P2PIX, P2PIX,
P2PIX__factory,
Reputation, Reputation,
} from "../../src/types"; } from "../../src/types";
@ -17,14 +19,6 @@ export interface Deploys {
token: string; token: string;
} }
// export interface Deposit {
// remaining: BigNumber;
// pixTarget: string;
// seller: string;
// token: string;
// valid: boolean;
// }
export interface Lock { export interface Lock {
sellerKey: BigNumber; sellerKey: BigNumber;
counter: BigNumber; counter: BigNumber;
@ -38,6 +32,16 @@ export interface Lock {
token: string; token: string;
} }
export interface Call {
target: string;
callData: string;
}
export interface Result {
success: boolean;
returnData: string;
}
export interface P2pixFixture { export interface P2pixFixture {
p2pix: P2PIX; p2pix: P2PIX;
erc20: MockToken; erc20: MockToken;
@ -49,19 +53,40 @@ export interface RepFixture {
reputation: Reputation; reputation: Reputation;
} }
type P2PixAndReputation = P2pixFixture & RepFixture; export interface MtcFixture {
multicall: Multicall;
}
type P2PixAndReputation = P2pixFixture &
RepFixture &
MtcFixture;
// exported constants // exported constants
export const getSignerAddrs = ( export const getSignerAddrs = (
amount: number, amount: number,
addrs: SignerWithAddress[], addrs: SignerWithAddress[],
): string[] => { ): string[] => {
const signers: string[] = []; return addrs.slice(0, amount).map(({ address }) => address);
const buffr = addrs.slice(0, amount); };
for (let i = 0; i < amount; i++) {
signers.push(buffr[i].address); export const getBnFrom = (nums: number[]): BigNumber[] => {
} const bns = nums.map(num => ethers.BigNumber.from(num));
return signers; return bns;
};
export const getLockData = (
addr: string,
locks: BigNumber[][],
): Call[] => {
const iface = new ethers.utils.Interface(
P2PIX__factory.abi,
);
return locks.map(lock => ({
target: addr,
callData: iface.encodeFunctionData("getLocksStatus", [
lock,
]),
}));
}; };
export const randomSigners = (amount: number): Signer[] => { export const randomSigners = (amount: number): Signer[] => {
@ -128,6 +153,11 @@ export async function p2pixFixture(): Promise<P2PixAndReputation> {
[true], [true],
)) as P2PIX; )) as P2PIX;
const Multicall = await ethers.getContractFactory(
"Multicall",
);
const multicall = (await Multicall.deploy()) as Multicall;
const signers = await ethers.getSigners(); const signers = await ethers.getSigners();
const whitelisted = signers.slice(0, 2); const whitelisted = signers.slice(0, 2);
const leaves = whitelisted.map(account => const leaves = whitelisted.map(account =>
@ -142,6 +172,7 @@ export async function p2pixFixture(): Promise<P2PixAndReputation> {
); );
return { return {
multicall,
reputation, reputation,
erc20, erc20,
p2pix, p2pix,

View File

@ -6049,16 +6049,17 @@ fsevents@~2.1.1:
languageName: node languageName: node
linkType: hard linkType: hard
"hardhat-tracer@npm:^1.2.0": "hardhat-tracer@npm:beta":
version: 1.2.0 version: 2.0.0-beta.6
resolution: "hardhat-tracer@npm:1.2.0" resolution: "hardhat-tracer@npm:2.0.0-beta.6"
dependencies: dependencies:
ethers: ^5.6.1 ethers: ^5.6.1
peerDependencies: peerDependencies:
chai: 4.x
chalk: 4.x chalk: 4.x
ethers: 5.x ethers: 5.x
hardhat: 2.x hardhat: 2.x
checksum: 1d348fb3ed60cbde2287329730ccd37c73af80cc2cf4ccfb045f26af26c7efebd4a6fdf611035f34ca7fb75d0eb95985e8f5ed4f0537d2615fb6e126d1d035f0 checksum: b14795adf3eecd487b874ef06799ab43c342a4908bcf58bbd0bc7274caa7976456a0c75a702aaf3a937fe7c8afbfe2e2a9f263b6a0c7e2fc56e6a54144288369
languageName: node languageName: node
linkType: hard linkType: hard
@ -8459,7 +8460,7 @@ fsevents@~2.1.1:
fs-extra: ^10.1.0 fs-extra: ^10.1.0
hardhat: ^2.12.2 hardhat: ^2.12.2
hardhat-gas-reporter: ^1.0.9 hardhat-gas-reporter: ^1.0.9
hardhat-tracer: ^1.2.0 hardhat-tracer: beta
husky: ^8.0.1 husky: ^8.0.1
keccak256: ^1.0.6 keccak256: ^1.0.6
lint-staged: ^13.0.3 lint-staged: ^13.0.3