test: 🚧 Added fixtures for new test schema
This commit is contained in:
@@ -17,11 +17,11 @@ library DataTypes {
|
||||
struct Lock {
|
||||
uint256 depositID;
|
||||
/// @dev Amount to be paid for relayer.
|
||||
uint256 relayerPremium;
|
||||
uint256 relayerPremium;
|
||||
/// @dev Amount to be tranfered via PIX.
|
||||
uint256 amount;
|
||||
uint256 amount;
|
||||
/// @dev If not paid at this block will be expired.
|
||||
uint256 expirationBlock;
|
||||
uint256 expirationBlock;
|
||||
/// @dev Where the tokens are sent the when order gets validated.
|
||||
address buyerAddress;
|
||||
/// @dev Relayer's target address that receives `relayerPremium` funds.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
pragma solidity 0.8.9;
|
||||
|
||||
interface EventAndErrors {
|
||||
|
||||
/// ███ Events ████████████████████████████████████████████████████████████
|
||||
|
||||
event DepositAdded(
|
||||
|
||||
@@ -5,41 +5,43 @@ import { IReputation } from "./lib/interfaces/IReputation.sol";
|
||||
import { Owned } from "./lib/auth/Owned.sol";
|
||||
import { FixedPointMathLib as WADMath } from "./lib/utils/FixedPointMathLib.sol";
|
||||
|
||||
contract Reputation is IReputation, Owned(msg.sender) {
|
||||
using WADMath for uint256;
|
||||
|
||||
contract Reputation is
|
||||
IReputation,
|
||||
Owned(msg.sender)
|
||||
{
|
||||
/// @dev Asymptote numerator constant value for the `limiter` fx.
|
||||
uint256 public constant maxLimit = 1e6;
|
||||
/// @dev Denominator's constant operand for the `limiter` fx.
|
||||
uint256 public constant magicValue = 2.5e11;
|
||||
|
||||
using WADMath for uint256;
|
||||
|
||||
/// @dev Asymptote numerator constant value for the `limiter` fx.
|
||||
uint256 constant public maxLimit = 1e6;
|
||||
/// @dev Denominator's constant operand for the `limiter` fx.
|
||||
uint256 constant public magicValue = 2.5e11;
|
||||
|
||||
constructor(/* */) {/* */}
|
||||
|
||||
function limiter(uint256 _userCredit)
|
||||
external
|
||||
pure
|
||||
override(IReputation)
|
||||
returns(uint256 _spendLimit)
|
||||
{
|
||||
// _spendLimit = 1 + ( ( maxLimit * _userCredit ) / sqrt( magicValue * ( _userCredit * _userCredit ) ) );
|
||||
// return _spendLimit;
|
||||
|
||||
|
||||
unchecked {
|
||||
uint256 numeratorWad =
|
||||
maxLimit.mulWadDown(_userCredit);
|
||||
uint256 userCreditSquaredWad =
|
||||
_userCredit.mulWadDown(_userCredit);
|
||||
uint256 denominatorSqrtWad =
|
||||
(userCreditSquaredWad.mulWadDown(magicValue)).sqrt();
|
||||
|
||||
_spendLimit = (1 + (numeratorWad).divWadDown(denominatorSqrtWad));
|
||||
constructor() /* */ {
|
||||
/* */
|
||||
}
|
||||
}
|
||||
|
||||
function limiter(
|
||||
uint256 _userCredit
|
||||
)
|
||||
external
|
||||
pure
|
||||
override(IReputation)
|
||||
returns (uint256 _spendLimit)
|
||||
{
|
||||
// _spendLimit = 1 + ( ( maxLimit * _userCredit ) / sqrt( magicValue * ( _userCredit * _userCredit ) ) );
|
||||
// return _spendLimit;
|
||||
|
||||
unchecked {
|
||||
uint256 numeratorWad = maxLimit.mulWadDown(
|
||||
_userCredit
|
||||
);
|
||||
uint256 userCreditSquaredWad = _userCredit
|
||||
.mulWadDown(_userCredit);
|
||||
uint256 denominatorSqrtWad = (
|
||||
userCreditSquaredWad.mulWadDown(magicValue)
|
||||
).sqrt();
|
||||
|
||||
_spendLimit = (1 +
|
||||
(numeratorWad).divWadDown(
|
||||
denominatorSqrtWad
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.4;
|
||||
|
||||
|
||||
interface IReputation {
|
||||
|
||||
function limiter(uint256 _userCredit)
|
||||
external
|
||||
pure
|
||||
returns(uint256 _spendLimit);
|
||||
|
||||
function limiter(
|
||||
uint256 _userCredit
|
||||
) external pure returns (uint256 _spendLimit);
|
||||
}
|
||||
|
||||
@@ -4,22 +4,27 @@ pragma solidity >=0.8.4;
|
||||
/// @notice Arithmetic library with operations for fixed-point numbers.
|
||||
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)
|
||||
library FixedPointMathLib {
|
||||
|
||||
/*//////////////////////////////////////////////////////////////
|
||||
SIMPLIFIED FIXED POINT OPERATIONS
|
||||
//////////////////////////////////////////////////////////////*/
|
||||
|
||||
/// @dev The scalar of ETH and most ERC20s.
|
||||
uint256 internal constant WAD = 1e18;
|
||||
uint256 internal constant WAD = 1e18;
|
||||
|
||||
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
|
||||
function mulWadDown(
|
||||
uint256 x,
|
||||
uint256 y
|
||||
) internal pure returns (uint256) {
|
||||
// Equivalent to (x * y) / WAD rounded down.
|
||||
return mulDivDown(x, y, WAD);
|
||||
return mulDivDown(x, y, WAD);
|
||||
}
|
||||
|
||||
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
|
||||
function divWadDown(
|
||||
uint256 x,
|
||||
uint256 y
|
||||
) internal pure returns (uint256) {
|
||||
// Equivalent to (x * WAD) / y rounded down.
|
||||
return mulDivDown(x, WAD, y);
|
||||
return mulDivDown(x, WAD, y);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////
|
||||
@@ -36,7 +41,12 @@ library FixedPointMathLib {
|
||||
z := mul(x, y)
|
||||
|
||||
// Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
|
||||
if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
|
||||
if iszero(
|
||||
and(
|
||||
iszero(iszero(denominator)),
|
||||
or(iszero(x), eq(div(z, x), y))
|
||||
)
|
||||
) {
|
||||
revert(0, 0)
|
||||
}
|
||||
|
||||
@@ -49,7 +59,9 @@ library FixedPointMathLib {
|
||||
GENERAL NUMBER UTILITIES
|
||||
//////////////////////////////////////////////////////////////*/
|
||||
|
||||
function sqrt(uint256 x) internal pure returns (uint256 z) {
|
||||
function sqrt(
|
||||
uint256 x
|
||||
) internal pure returns (uint256 z) {
|
||||
assembly {
|
||||
let y := x // We start y at x, which will help us make our initial estimate.
|
||||
|
||||
@@ -60,7 +72,9 @@ library FixedPointMathLib {
|
||||
|
||||
// We check y >= 2^(k + 8) but shift right by k bits
|
||||
// each branch to ensure that if x >= 256, then y >= 256.
|
||||
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
|
||||
if iszero(
|
||||
lt(y, 0x10000000000000000000000000000000000)
|
||||
) {
|
||||
y := shr(128, y)
|
||||
z := shl(64, z)
|
||||
}
|
||||
@@ -112,4 +126,4 @@ library FixedPointMathLib {
|
||||
z := sub(z, lt(div(x, z), z))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,42 +2,57 @@
|
||||
pragma solidity >=0.8.4;
|
||||
|
||||
/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
|
||||
/// @author Solady
|
||||
/// @author Solady
|
||||
/// (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
|
||||
/// @author Modified from Solmate
|
||||
/// @author Modified from Solmate
|
||||
/// (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
|
||||
/// @author Modified from OpenZeppelin
|
||||
/// @author Modified from OpenZeppelin
|
||||
/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
|
||||
library MerkleProofLib {
|
||||
/// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
|
||||
function verify(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
|
||||
internal
|
||||
pure
|
||||
returns (bool isValid)
|
||||
{
|
||||
function verify(
|
||||
bytes32[] calldata proof,
|
||||
bytes32 root,
|
||||
bytes32 leaf
|
||||
) internal pure returns (bool isValid) {
|
||||
/// @solidity memory-safe-assembly
|
||||
assembly {
|
||||
if proof.length {
|
||||
// Left shift by 5 is equivalent to multiplying by 0x20.
|
||||
let end := add(proof.offset, shl(5, proof.length))
|
||||
let end := add(
|
||||
proof.offset,
|
||||
shl(5, proof.length)
|
||||
)
|
||||
// Initialize `offset` to the offset of `proof` in the calldata.
|
||||
let offset := proof.offset
|
||||
// Iterate over proof elements to compute root hash.
|
||||
for {} 1 {} {
|
||||
for {
|
||||
|
||||
} 1 {
|
||||
|
||||
} {
|
||||
// Slot of `leaf` in scratch space.
|
||||
// If the condition is true: 0x20, otherwise: 0x00.
|
||||
let scratch := shl(5, gt(leaf, calldataload(offset)))
|
||||
let scratch := shl(
|
||||
5,
|
||||
gt(leaf, calldataload(offset))
|
||||
)
|
||||
// Store elements to hash contiguously in scratch space.
|
||||
// Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
|
||||
mstore(scratch, leaf)
|
||||
mstore(xor(scratch, 0x20), calldataload(offset))
|
||||
mstore(
|
||||
xor(scratch, 0x20),
|
||||
calldataload(offset)
|
||||
)
|
||||
// Reuse `leaf` to store the hash to reduce stack operations.
|
||||
leaf := keccak256(0x00, 0x40)
|
||||
offset := add(offset, 0x20)
|
||||
if iszero(lt(offset, end)) { break }
|
||||
if iszero(lt(offset, end)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
isValid := eq(leaf, root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.4;
|
||||
pragma solidity >=0.8.4;
|
||||
|
||||
/// @notice Reentrancy protection for smart contracts.
|
||||
/// @author z0r0z.eth
|
||||
@@ -31,4 +31,4 @@ abstract contract ReentrancyGuard {
|
||||
function clearReentrancyGuard() internal virtual {
|
||||
guard = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,12 +82,7 @@ contract P2PIX is
|
||||
uint256 _amount,
|
||||
string calldata _pixTarget,
|
||||
bytes32 allowlistRoot
|
||||
)
|
||||
public
|
||||
returns (
|
||||
uint256 depositID
|
||||
)
|
||||
{
|
||||
) public returns (uint256 depositID) {
|
||||
ERC20 t = ERC20(_token);
|
||||
if (!allowedERC20s[t]) revert TokenDenied();
|
||||
|
||||
@@ -143,9 +138,9 @@ contract P2PIX is
|
||||
|
||||
/// @notice Public method designed to lock an remaining amount of
|
||||
/// the deposit order of a seller.
|
||||
/// @dev This method can be performed either by:
|
||||
/// @dev 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;
|
||||
/// - An user with enough userRecord to lock the wished amount;
|
||||
/// @dev There can only exist a lock per each `_amount` partitioned
|
||||
/// from the total `remaining` value.
|
||||
/// @dev Locks can only be performed in valid orders.
|
||||
@@ -153,7 +148,7 @@ contract P2PIX is
|
||||
/// @param _relayerTarget Target address entitled to the `relayerPremium`.
|
||||
/// @param _relayerPremium The refund/premium owed to a relayer.
|
||||
/// @param _amount The deposit's remaining amount wished to be locked.
|
||||
/// @param merkleProof This value should be:
|
||||
/// @param merkleProof This value should be:
|
||||
/// - Provided as a pass if the `msg.sender` is in the seller's allowlist;
|
||||
/// - Left empty otherwise;
|
||||
/// @param expiredLocks An array of `bytes32` identifiers to be
|
||||
@@ -211,8 +206,7 @@ contract P2PIX is
|
||||
|
||||
// Halt execution and output `lockID`.
|
||||
return lockID;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
uint256 userCredit = userRecord[
|
||||
_castAddrToKey(msg.sender)
|
||||
];
|
||||
@@ -239,15 +233,15 @@ contract P2PIX is
|
||||
|
||||
/// @notice Lock release method that liquidate lock
|
||||
/// orders and distributes relayer fees.
|
||||
/// @dev This method can be called by any public actor
|
||||
/// @dev This method can be called by any public actor
|
||||
/// as long the signature provided is valid.
|
||||
/// @dev `relayerPremium` gets splitted equaly
|
||||
/// @dev `relayerPremium` gets splitted equaly
|
||||
/// if `relayerTarget` addresses differ.
|
||||
/// @dev If the `msg.sender` of this method and `l.relayerAddress` are the same,
|
||||
/// `msg.sender` accrues both l.amount and l.relayerPremium as userRecord credit.
|
||||
/// In case of they differing:
|
||||
/// - `lock` caller gets accrued with `l.amount` as userRecord credit;
|
||||
/// - `release` caller gets accrued with `l.relayerPremium` as userRecord credit;
|
||||
/// - `release` caller gets accrued with `l.relayerPremium` as userRecord credit;
|
||||
/// @param _relayerTarget Target address entitled to the `relayerPremim`.
|
||||
/// @dev Function sighash: 0x4e1389ed.
|
||||
function release(
|
||||
@@ -342,12 +336,12 @@ contract P2PIX is
|
||||
/// @notice Unlocks expired locks.
|
||||
/// @dev Triggered in the callgraph by both `lock` and `withdraw` functions.
|
||||
/// @dev This method can also have any public actor as its `tx.origin`.
|
||||
/// @dev For each successfull unexpired lock recovered,
|
||||
/// @dev For each successfull unexpired lock recovered,
|
||||
/// `userRecord[_castAddrToKey(l.relayerAddress)]` is decreased by half of its value.
|
||||
/// @dev Function sighash: 0x8e2749d6.
|
||||
function unlockExpired(bytes32[] calldata lockIDs)
|
||||
public
|
||||
{
|
||||
function unlockExpired(
|
||||
bytes32[] calldata lockIDs
|
||||
) public {
|
||||
uint256 i;
|
||||
uint256 locksSize = lockIDs.length;
|
||||
|
||||
@@ -359,13 +353,14 @@ contract P2PIX is
|
||||
mapDeposits[l.depositID].remaining += l.amount;
|
||||
l.amount = 0;
|
||||
|
||||
uint256 userKey =
|
||||
_castAddrToKey(l.relayerAddress);
|
||||
uint256 _newUserRecord =
|
||||
(userRecord[userKey] >> 1);
|
||||
uint256 userKey = _castAddrToKey(
|
||||
l.relayerAddress
|
||||
);
|
||||
uint256 _newUserRecord = (userRecord[userKey] >>
|
||||
1);
|
||||
|
||||
if (_newUserRecord <= 100) {
|
||||
userRecord[userKey] = 100;
|
||||
userRecord[userKey] = 100;
|
||||
} else {
|
||||
userRecord[userKey] = _newUserRecord;
|
||||
}
|
||||
@@ -414,9 +409,10 @@ contract P2PIX is
|
||||
emit DepositWithdrawn(msg.sender, depositID, amount);
|
||||
}
|
||||
|
||||
function setRoot(address addr, bytes32 merkleroot)
|
||||
public
|
||||
{
|
||||
function setRoot(
|
||||
address addr,
|
||||
bytes32 merkleroot
|
||||
) public {
|
||||
if (addr == msg.sender) {
|
||||
sellerAllowList[
|
||||
_castAddrToKey(addr)
|
||||
@@ -434,30 +430,27 @@ contract P2PIX is
|
||||
emit FundsWithdrawn(msg.sender, balance);
|
||||
}
|
||||
|
||||
function setReputation(IReputation _reputation)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
function setReputation(
|
||||
IReputation _reputation
|
||||
) public onlyOwner {
|
||||
assembly {
|
||||
sstore(reputation.slot, _reputation)
|
||||
}
|
||||
emit ReputationUpdated(address(_reputation));
|
||||
}
|
||||
|
||||
function setDefaultLockBlocks(uint256 _blocks)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
function setDefaultLockBlocks(
|
||||
uint256 _blocks
|
||||
) public onlyOwner {
|
||||
assembly {
|
||||
sstore(defaultLockBlocks.slot, _blocks)
|
||||
}
|
||||
emit LockBlocksUpdated(_blocks);
|
||||
}
|
||||
|
||||
function setValidSigners(address[] memory _validSigners)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
function setValidSigners(
|
||||
address[] memory _validSigners
|
||||
) public onlyOwner {
|
||||
unchecked {
|
||||
uint256 i;
|
||||
uint256 len = _validSigners.length;
|
||||
@@ -626,11 +619,9 @@ contract P2PIX is
|
||||
) revert AddressDenied();
|
||||
}
|
||||
|
||||
function _limiter(uint256 _userCredit)
|
||||
internal
|
||||
view
|
||||
returns (uint256 _spendLimit)
|
||||
{
|
||||
function _limiter(
|
||||
uint256 _userCredit
|
||||
) internal view returns (uint256 _spendLimit) {
|
||||
// enconde the fx sighash and args
|
||||
bytes memory encodedParams = abi.encodeWithSelector(
|
||||
IReputation.limiter.selector,
|
||||
@@ -670,11 +661,9 @@ contract P2PIX is
|
||||
/// @notice Public method that handles `address`
|
||||
/// to `uint256` safe type casting.
|
||||
/// @dev Function sighash: 0x4b2ae980.
|
||||
function _castAddrToKey(address _addr)
|
||||
public
|
||||
pure
|
||||
returns (uint256 _key)
|
||||
{
|
||||
function _castAddrToKey(
|
||||
address _addr
|
||||
) public pure returns (uint256 _key) {
|
||||
_key = uint256(uint160(address(_addr))) << 12;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user