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