feat: 🚧 Deposit struct replaced for packed uint

This commit is contained in:
PedroCailleret 2022-12-20 01:39:35 -03:00
parent 5416bbdd72
commit 0d612572c6
14 changed files with 3092 additions and 2377 deletions

View File

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

View File

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

View File

@ -18,11 +18,21 @@
"name": "AmountNotAllowed", "name": "AmountNotAllowed",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "DecOverflow",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "DepositAlreadyExists", "name": "DepositAlreadyExists",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "EmptyPixTarget",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "InvalidDeposit", "name": "InvalidDeposit",
@ -48,6 +58,11 @@
"name": "LoopOverflow", "name": "LoopOverflow",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "MaxBalExceeded",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "NoTokens", "name": "NoTokens",
@ -63,6 +78,11 @@
"name": "NotExpired", "name": "NotExpired",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "NotInitialized",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "OnlySeller", "name": "OnlySeller",
@ -111,12 +131,6 @@
"name": "seller", "name": "seller",
"type": "address" "type": "address"
}, },
{
"indexed": false,
"internalType": "uint256",
"name": "depositID",
"type": "uint256"
},
{ {
"indexed": false, "indexed": false,
"internalType": "address", "internalType": "address",
@ -144,29 +158,10 @@
}, },
{ {
"indexed": false, "indexed": false,
"internalType": "uint256",
"name": "depositID",
"type": "uint256"
}
],
"name": "DepositClosed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address", "internalType": "address",
"name": "seller", "name": "token",
"type": "address" "type": "address"
}, },
{
"indexed": false,
"internalType": "uint256",
"name": "depositID",
"type": "uint256"
},
{ {
"indexed": false, "indexed": false,
"internalType": "uint256", "internalType": "uint256",
@ -214,7 +209,7 @@
{ {
"indexed": false, "indexed": false,
"internalType": "uint256", "internalType": "uint256",
"name": "depositID", "name": "seller",
"type": "uint256" "type": "uint256"
}, },
{ {
@ -254,6 +249,12 @@
"internalType": "bytes32", "internalType": "bytes32",
"name": "lockId", "name": "lockId",
"type": "bytes32" "type": "bytes32"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
} }
], ],
"name": "LockReleased", "name": "LockReleased",
@ -310,6 +311,31 @@
"name": "RootUpdated", "name": "RootUpdated",
"type": "event" "type": "event"
}, },
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "seller",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "state",
"type": "bool"
}
],
"name": "ValidSet",
"type": "event"
},
{ {
"anonymous": false, "anonymous": false,
"inputs": [ "inputs": [

View File

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

File diff suppressed because one or more lines are too long

View File

@ -2,26 +2,28 @@
pragma solidity 0.8.9; pragma solidity 0.8.9;
library DataTypes { library DataTypes {
struct Deposit { // struct Deposit {
/// @dev Remaining tokens available. // /// @dev Remaining tokens available.
uint256 remaining; // uint256 remaining;
/// @dev The PIX account for the seller receive transactions. // /// @dev The PIX account for the seller receive transactions.
string pixTarget; // string pixTarget;
address seller; // address seller;
/// @dev ERC20 stable token address. // /// @dev ERC20 stable token address.
address token; // address token;
/// @dev Could be invalidated by the seller. // /// @dev Could be invalidated by the seller.
bool valid; // bool valid;
} // }
struct Lock { struct Lock {
uint256 depositID; uint256 sellerKey;
uint256 counter;
/// @dev Amount to be paid for relayer. /// @dev Amount to be paid for relayer.
uint256 relayerPremium; uint256 relayerPremium;
/// @dev Amount to be tranfered via PIX. /// @dev Amount to be tranfered via PIX.
uint256 amount; uint256 amount;
/// @dev If not paid at this block will be expired. /// @dev If not paid at this block will be expired.
uint256 expirationBlock; uint256 expirationBlock;
uint160 pixTarget;
/// @dev Where the tokens are sent the when order gets validated. /// @dev Where the tokens are sent the when order gets validated.
address buyerAddress; address buyerAddress;
/// @dev Relayer's target address that receives `relayerPremium` funds. /// @dev Relayer's target address that receives `relayerPremium` funds.
@ -29,5 +31,6 @@ library DataTypes {
/// @dev Relayer address (msg.sender) that facilitated this transaction. /// @dev Relayer address (msg.sender) that facilitated this transaction.
/// @dev Reputation points accruer. /// @dev Reputation points accruer.
address relayerAddress; address relayerAddress;
address token;
} }
} }

View File

@ -7,28 +7,30 @@ interface EventAndErrors {
event DepositAdded( event DepositAdded(
address indexed seller, address indexed seller,
uint256 depositID, // uint256 depositID,
address token, address token,
uint256 amount uint256 amount
); );
event DepositClosed( event ValidSet(
address indexed seller, address indexed seller,
uint256 depositID address token,
bool state
); );
event DepositWithdrawn( event DepositWithdrawn(
address indexed seller, address indexed seller,
uint256 depositID, address token,
uint256 amount uint256 amount
); );
event LockAdded( event LockAdded(
address indexed buyer, address indexed buyer,
bytes32 indexed lockID, bytes32 indexed lockID,
uint256 depositID, uint256 seller,
uint256 amount uint256 amount
); );
event LockReleased( event LockReleased(
address indexed buyer, address indexed buyer,
bytes32 lockId bytes32 lockId,
uint256 amount
); );
event LockReturned( event LockReturned(
address indexed buyer, address indexed buyer,
@ -103,4 +105,11 @@ interface EventAndErrors {
/// @dev Reverts on an expired lock. /// @dev Reverts on an expired lock.
/// @dev 0xf6fafba0 /// @dev 0xf6fafba0
error LockExpired(); error LockExpired();
/// @dev 0xce3a3d37
error DecOverflow();
/// @dev 0x
error MaxBalExceeded();
error EmptyPixTarget();
error NotInitialized();
} }

View File

@ -9,7 +9,7 @@ pragma solidity 0.8.9;
/// ///
import { Owned } from "./lib/auth/Owned.sol"; import { Owned } from "./lib/auth/Owned.sol";
import { Counters } from "./lib/utils/Counters.sol"; // import { Counters } from "./lib/utils/Counters.sol";
import { ERC20, SafeTransferLib } from "./lib/utils/SafeTransferLib.sol"; import { ERC20, SafeTransferLib } from "./lib/utils/SafeTransferLib.sol";
import { IReputation } from "./lib/interfaces/IReputation.sol"; import { IReputation } from "./lib/interfaces/IReputation.sol";
import { MerkleProofLib as Merkle } from "./lib/utils/MerkleProofLib.sol"; import { MerkleProofLib as Merkle } from "./lib/utils/MerkleProofLib.sol";
@ -25,36 +25,53 @@ contract P2PIX is
// solhint-disable use-forbidden-name // solhint-disable use-forbidden-name
// solhint-disable no-inline-assembly // solhint-disable no-inline-assembly
using Counters for Counters.Counter; // using Counters for Counters.Counter;
using DT for DT.Deposit;
using DT for DT.Lock; using DT for DT.Lock;
/// Constants
/// @dev The bitmask of `sellerBalance` entry.
uint256 constant private BITMASK_SB_ENTRY = (1 << 94) - 1;
/// @dev The bit position of `pixTarget` in `sellerBalance`.
uint256 constant private BITPOS_PIXTARGET = 95;
/// @dev The bit position of `valid` in `sellerBalance`.
uint256 constant private BITPOS_VALID = 255;
/// @dev The bitmask of all 256 bits of `sellerBalance` except for the last one.
uint256 constant private BITMASK_VALID = (1 << 255) - 1;
/// @dev The scalar of BRZ token.
uint256 constant public WAD = 1e18;
/// Storage /// Storage
IReputation public reputation; IReputation public reputation;
Counters.Counter public depositCount; // Counters.Counter public depositCount;
/// @dev Default blocks that lock will hold tokens. /// @dev Default blocks that lock will hold tokens.
uint256 public defaultLockBlocks; uint256 public defaultLockBlocks;
/// @dev The scalar of BRZ token. uint256 public lockCounter;
uint256 constant public WAD = 1e18;
/// @dev List of Locks.
mapping(bytes32 => DT.Lock) public mapLocks;
/// @dev Seller casted to key => Seller's allowlist merkleroot.
mapping(uint256 => bytes32) public sellerAllowList;
/// @dev Stores an relayer's last computed credit. /// @dev Stores an relayer's last computed credit.
mapping(uint256 => uint256) public userRecord; mapping(uint256 => uint256) public userRecord;
/// @dev List of valid Bacen signature addresses /// @dev List of valid Bacen signature addresses
mapping(uint256 => bool) public validBacenSigners; mapping(uint256 => bool) public validBacenSigners;
/// @dev Seller list of deposits
mapping(uint256 => DT.Deposit) public mapDeposits;
/// @dev List of Locks.
mapping(bytes32 => DT.Lock) public mapLocks;
/// @dev List of Pix transactions already signed. /// @dev List of Pix transactions already signed.
mapping(bytes32 => bool) public usedTransactions; mapping(bytes32 => bool) public usedTransactions;
/// @dev Seller casted to key => Seller's allowlist merkleroot.
mapping(uint256 => bytes32) public sellerAllowList;
/// @dev Tokens allowed to serve as the underlying amount of a deposit. /// @dev Tokens allowed to serve as the underlying amount of a deposit.
mapping(ERC20 => bool) public allowedERC20s; mapping(ERC20 => bool) public allowedERC20s;
// BITS LAYOUT
// `uint96` [0...94] := balance
// `uint160` [95...254] := pixTarget
// `bool` [255] := valid
/// @dev `balance` max. value = 10**26.
/// @dev `pixTarget` keys are restricted to 160 bits.
mapping(uint256 => mapping(ERC20 => uint256)) public sellerBalance;
/// Constructor /// Constructor
constructor( constructor(
@ -77,27 +94,29 @@ contract P2PIX is
/// @dev Seller needs to send his tokens to the P2PIX smart contract. /// @dev Seller needs to send his tokens to the P2PIX smart contract.
/// @param _pixTarget Pix key destination provided by the offer's seller. /// @param _pixTarget Pix key destination provided by the offer's seller.
/// @param allowlistRoot Optional allow list merkleRoot update `bytes32` value. /// @param allowlistRoot Optional allow list merkleRoot update `bytes32` value.
/// @return depositID The `uint256` return value provided
/// as the deposit identifier. /// as the deposit identifier.
/// @dev Function sighash: 0xbfe07da6. /// @dev Function sighash: 0xbfe07da6.
function deposit( function deposit(
address _token, address _token,
uint256 _amount, uint96 _amount,
string calldata _pixTarget, uint160 _pixTarget,
bool _valid,
bytes32 allowlistRoot bytes32 allowlistRoot
) public returns (uint256 depositID) { ) public {
ERC20 t = ERC20(_token); ERC20 t = ERC20(_token);
if (!allowedERC20s[t]) revert TokenDenied(); uint256 k = _castAddrToKey(msg.sender);
(depositID) = _encodeDepositID(); if(_pixTarget == 0)
revert EmptyPixTarget();
if (!allowedERC20s[t])
revert TokenDenied();
uint256 _sellerBalance =
sellerBalance[k][t];
DT.Deposit memory d = DT.Deposit({ uint256 currBal =
remaining: _amount, _sellerBalance & BITMASK_SB_ENTRY;
pixTarget: _pixTarget, if ((currBal + _amount) > 1e8 ether)
seller: msg.sender, revert MaxBalExceeded();
token: _token,
valid: true
});
setReentrancyGuard(); setReentrancyGuard();
@ -105,8 +124,15 @@ contract P2PIX is
setRoot(msg.sender, allowlistRoot); setRoot(msg.sender, allowlistRoot);
} }
mapDeposits[depositID] = d; uint256 amountCasted;
depositCount.increment(); uint256 pixTargetCasted;
uint256 validCasted;
(amountCasted, pixTargetCasted, validCasted) =
_castToUint(_amount, _pixTarget, _valid);
sellerBalance[k][t] =
(currBal + amountCasted) |
(pixTargetCasted << BITPOS_PIXTARGET) |
(validCasted << BITPOS_VALID);
SafeTransferLib.safeTransferFrom( SafeTransferLib.safeTransferFrom(
t, t,
@ -119,7 +145,6 @@ contract P2PIX is
emit DepositAdded( emit DepositAdded(
msg.sender, msg.sender,
depositID,
_token, _token,
_amount _amount
); );
@ -129,14 +154,26 @@ contract P2PIX is
/// locks made to his/her token offering order. /// locks made to his/her token offering order.
/// @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 {
uint256 key = _castAddrToKey(msg.sender);
uint256 _sellerBalance =
sellerBalance[key][token];
if (_sellerBalance != 0) {
uint256 _valid;
assembly {
_valid := state
}
_sellerBalance = (_sellerBalance & BITMASK_VALID) |
(_valid << BITPOS_VALID);
sellerBalance[key][token] = _sellerBalance;
function cancelDeposit(uint256 depositID) public { emit ValidSet(
_onlySeller(depositID); msg.sender,
mapDeposits[depositID].valid = false; address(token),
emit DepositClosed( state
mapDeposits[depositID].seller,
depositID
); );
} else
revert NotInitialized();
} }
/// @notice Public method designed to lock an remaining amount of /// @notice Public method designed to lock an remaining amount of
@ -159,7 +196,8 @@ contract P2PIX is
/// @return lockID The `bytes32` value returned as the lock identifier. /// @return lockID The `bytes32` value returned as the lock identifier.
/// @dev Function sighash: 0x03aaf306. /// @dev Function sighash: 0x03aaf306.
function lock( function lock(
uint256 _depositID, address _seller,
address _token,
address _buyerAddress, address _buyerAddress,
address _relayerTarget, address _relayerTarget,
uint256 _relayerPremium, uint256 _relayerPremium,
@ -168,44 +206,77 @@ contract P2PIX is
bytes32[] calldata expiredLocks bytes32[] calldata expiredLocks
) public nonReentrant returns (bytes32 lockID) { ) public nonReentrant returns (bytes32 lockID) {
unlockExpired(expiredLocks); unlockExpired(expiredLocks);
DT.Deposit storage d = mapDeposits[_depositID]; ERC20 t = ERC20(_token);
if (!getValid(_seller, t))
revert InvalidDeposit();
uint256 bal = getBalance(_seller, t);
if (bal < _amount)
revert NotEnoughTokens();
if (!d.valid) revert InvalidDeposit(); uint256 k =
if (d.remaining < _amount) revert NotEnoughTokens(); _castAddrToKey(_seller);
(lockID) = _encodeLockID( uint256 cachedCounter =
_depositID, lockCounter + 1;
lockID = keccak256(
abi.encodePacked(
lockCounter,
_amount, _amount,
_buyerAddress _buyerAddress
)
); );
if (mapLocks[lockID].expirationBlock >= block.number)
revert NotExpired();
DT.Lock memory l = DT.Lock({ DT.Lock memory l = DT.Lock(
depositID: _depositID, k,
relayerPremium: _relayerPremium, cachedCounter,
amount: _amount, _relayerPremium,
expirationBlock: (block.number + _amount,
defaultLockBlocks), (block.number + defaultLockBlocks),
buyerAddress: _buyerAddress, uint160(sellerBalance[k][t] >> BITPOS_PIXTARGET),
relayerTarget: _relayerTarget, _buyerAddress,
relayerAddress: msg.sender _relayerTarget,
}); msg.sender,
address(t)
);
if (merkleProof.length != 0) { if (merkleProof.length != 0) {
merkleVerify( merkleVerify(
merkleProof, merkleProof,
sellerAllowList[_castAddrToKey(d.seller)], sellerAllowList[k],
msg.sender msg.sender
); );
_addLock(lockID, l, d); _addLock(
bal,
_amount,
lockID,
l,
t,
k);
lockCounter++;
// Halt execution and output `lockID`. // Halt execution and output `lockID`.
return lockID; return lockID;
} else { } else {
if (l.amount <= 1e2 ether) { if (l.amount <= 1e2 ether) {
_addLock(lockID, l, d); _addLock(
bal,
_amount,
lockID,
l,
t,
k);
lockCounter++;
// Halt execution and output `lockID`. // Halt execution and output `lockID`.
return lockID; return lockID;
} else { } else {
uint256 userCredit = userRecord[ uint256 userCredit = userRecord[
_castAddrToKey(msg.sender) _castAddrToKey(msg.sender)
@ -213,10 +284,20 @@ contract P2PIX is
uint256 spendLimit; uint256 spendLimit;
(spendLimit) = _limiter(userCredit / WAD); (spendLimit) = _limiter(userCredit / WAD);
if (l.amount > (spendLimit * WAD) || l.amount > 1e6 ether) if (l.amount > (spendLimit * WAD) ||
l.amount > 1e6 ether)
revert AmountNotAllowed(); revert AmountNotAllowed();
_addLock(lockID, l, d); _addLock(
bal,
_amount,
lockID,
l,
t,
k);
lockCounter++;
// Halt execution and output `lockID`. // Halt execution and output `lockID`.
return lockID; return lockID;
} }
@ -250,10 +331,9 @@ contract P2PIX is
if (l.expirationBlock < block.number) if (l.expirationBlock < block.number)
revert LockExpired(); revert LockExpired();
DT.Deposit storage d = mapDeposits[l.depositID];
bytes32 message = keccak256( bytes32 message = keccak256(
abi.encodePacked( abi.encodePacked(
d.pixTarget, l.pixTarget,
l.amount, l.amount,
pixTimestamp pixTimestamp
) )
@ -275,7 +355,7 @@ contract P2PIX is
if (!validBacenSigners[signer]) if (!validBacenSigners[signer])
revert InvalidSigner(); revert InvalidSigner();
ERC20 t = ERC20(d.token); ERC20 t = ERC20(l.token);
// We cache values before zeroing them out. // We cache values before zeroing them out.
uint256 lockAmount = l.amount; uint256 lockAmount = l.amount;
@ -324,7 +404,7 @@ contract P2PIX is
} }
} }
emit LockReleased(l.buyerAddress, lockID); emit LockReleased(l.buyerAddress, lockID, lockAmount);
} }
/// @notice Unlocks expired locks. /// @notice Unlocks expired locks.
@ -344,7 +424,13 @@ contract P2PIX is
_notExpired(l); _notExpired(l);
mapDeposits[l.depositID].remaining += l.amount; 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;
l.amount = 0; l.amount = 0;
uint256 userKey = _castAddrToKey( uint256 userKey = _castAddrToKey(
@ -379,28 +465,44 @@ contract P2PIX is
/// tokens from expired deposits. /// tokens from expired deposits.
/// @dev Function sighash: 0x36317972. /// @dev Function sighash: 0x36317972.
function withdraw( function withdraw(
uint256 depositID, ERC20 token,
bytes32[] calldata expiredLocks bytes32[] calldata expiredLocks
) public nonReentrant { )
_onlySeller(depositID); public
nonReentrant
returns(uint256 _sellerBalance)
{
unlockExpired(expiredLocks); unlockExpired(expiredLocks);
DT.Deposit storage d = mapDeposits[depositID]; if (getValid(msg.sender, token)
== true
if (d.valid == true) { ) {
cancelDeposit(depositID); setValidState(token, false);
} }
ERC20 token = ERC20(d.token); uint256 key =
_castAddrToKey(msg.sender);
// Withdraw remaining tokens from mapDeposit[depositID] sellerBalance[key][token] -=
uint256 amount = d.remaining; (_sellerBalance =
d.remaining = 0; sellerBalance[key][token]
& BITMASK_SB_ENTRY);
if(_sellerBalance == 0)
revert InvalidDeposit();
// safeTransfer tokens to seller // safeTransfer tokens to seller
SafeTransferLib.safeTransfer(token, d.seller, amount); SafeTransferLib.safeTransfer(
token,
msg.sender,
_sellerBalance
);
emit DepositWithdrawn(msg.sender, depositID, amount); emit DepositWithdrawn(
msg.sender,
address(token),
_sellerBalance
);
} }
function setRoot( function setRoot(
@ -481,7 +583,7 @@ contract P2PIX is
let tLoc := add(_tokens, 0x20) let tLoc := add(_tokens, 0x20)
let sLoc := add(_states, 0x20) let sLoc := add(_states, 0x20)
for { for {
let end := add(tLoc, mul(tLen, 0x20)) let end := add(tLoc, shl(5, tLen))
} iszero(eq(tLoc, end)) { } iszero(eq(tLoc, end)) {
tLoc := add(tLoc, 0x20) tLoc := add(tLoc, 0x20)
sLoc := add(sLoc, 0x20) sLoc := add(sLoc, 0x20)
@ -508,14 +610,6 @@ contract P2PIX is
// solhint-disable-next-line no-empty-blocks // solhint-disable-next-line no-empty-blocks
receive() external payable {} receive() external payable {}
/// @notice Access control private view method that
/// performs auth check on an deposit's seller.
/// @dev Function sighash: 0x4125a4d9.
function _onlySeller(uint256 _depositID) private view {
if (mapDeposits[_depositID].seller != msg.sender)
revert OnlySeller();
}
/// @notice Private view auxiliar logic that reverts /// @notice Private view auxiliar logic that reverts
/// on a not expired lock passed as argument of the function. /// on a not expired lock passed as argument of the function.
/// @dev Called exclusively by the `unlockExpired` method. /// @dev Called exclusively by the `unlockExpired` method.
@ -526,31 +620,74 @@ contract P2PIX is
if (_l.amount == 0) revert AlreadyReleased(); if (_l.amount == 0) revert AlreadyReleased();
} }
/// @notice Internal view auxiliar logic that returns a new valid `_depositID`.
/// @dev It reverts on an already valid counter (`uint256`) value.
/// @dev Function sighash: 0xdb51d697.
function _encodeDepositID()
internal
view
returns (uint256 _depositID)
{
(_depositID) = depositCount.current();
}
function _addLock( function _addLock(
uint256 _bal,
uint256 _amount,
bytes32 _lockID, bytes32 _lockID,
DT.Lock memory _l, DT.Lock memory _l,
DT.Deposit storage _d ERC20 _t,
uint256 _k
) internal { ) internal {
mapLocks[_lockID] = _l; mapLocks[_lockID] = _l;
_d.remaining -= _l.amount;
assembly {
if iszero(
iszero(
or(
iszero(_bal),
lt(
sub(
_bal,
_amount),
0x0
)))) {
// DecOverflow()
mstore(0x00, 0xce3a3d37)
revert(0x1c, 0x04)
}
}
// we can directly dec from packed uint entry value
sellerBalance[_k][_t] -= _amount;
emit LockAdded( emit LockAdded(
_l.buyerAddress, _l.buyerAddress,
_lockID, _lockID,
_l.depositID, _l.sellerKey,
_l.amount _l.amount
); );
/// @todo
// assembly {
// // sstore(mp.slot, _l)
// mstore(0x00, _k)
// mstore(0x20, sellerBalance.slot)
// let sbkslot := keccak256(0x00, 0x40)
// mstore(0x00, _t)
// mstore(0x20, sbkslot)
// let sbslot := keccak256(0x00,0x40)
// let oldsb := sload(sbslot)
// sstore(
// sbslot,
// or(
// or(
// _newBal,
// shr(
// oldsb,
// BITPOS_PIXTARGET
// )),
// and(
// shr(
// oldsb,
// BITPOS_VALID
// ),
// BITMASK_SB_ENTRY
// )
// )
// )
// }
} }
/// @notice Private view auxiliar logic that encodes/returns /// @notice Private view auxiliar logic that encodes/returns
@ -559,21 +696,21 @@ contract P2PIX is
/// as argument of the function. /// as argument of the function.
/// @dev Called exclusively by the `lock` method. /// @dev Called exclusively by the `lock` method.
/// @dev Function sighash: 0x3fc5fb52. /// @dev Function sighash: 0x3fc5fb52.
function _encodeLockID( // function _encodeLockID(
uint256 _depositID, // uint256 _lockCounter,
uint256 _amount, // uint256 _amount,
address _buyerAddress // address _buyerAddress
) private view returns (bytes32 _lockID) { // ) private view returns (bytes32 _lockID) {
_lockID = keccak256( // _lockID = keccak256(
abi.encodePacked( // abi.encodePacked(
_depositID, // _lockCounter,
_amount, // _amount,
_buyerAddress // _buyerAddress
) // )
); // );
if (mapLocks[_lockID].expirationBlock >= block.number) // if (mapLocks[_lockID].expirationBlock >= block.number)
revert NotExpired(); // revert NotExpired();
} // }
function merkleVerify( function merkleVerify(
bytes32[] calldata _merkleProof, bytes32[] calldata _merkleProof,
@ -628,6 +765,69 @@ contract P2PIX is
} }
} }
function _castToUint(
uint96 _amount,
uint160 _pixTarget,
bool _valid)
private
pure
returns (
uint256 _amountCasted,
uint256 _pixTargetCasted,
uint256 _validCasted
) {
assembly {
_amountCasted := _amount
_pixTargetCasted := _pixTarget
_validCasted := _valid
}
}
function getBalance(
address seller,
ERC20 token
)
public
view
returns(uint256 bal)
{
bal =
sellerBalance[
_castAddrToKey(seller)
][token] & BITMASK_SB_ENTRY;
}
function getValid(
address seller,
ERC20 token
)
public
view
returns(bool valid)
{
uint256 b =
(sellerBalance[
_castAddrToKey(seller)
][token] >> BITPOS_VALID) & BITMASK_SB_ENTRY;
assembly { valid := b }
}
function getPixTarget(
address seller,
ERC20 token
)
public
view
returns(uint160 pixTarget)
{
pixTarget =
uint160(
sellerBalance[
_castAddrToKey(seller)
][token] >> BITPOS_PIXTARGET
);
}
/// @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.
@ -636,4 +836,10 @@ contract P2PIX is
) public pure returns (uint256 _key) { ) public pure returns (uint256 _key) {
_key = uint256(uint160(address(_addr))) << 12; _key = uint256(uint160(address(_addr))) << 12;
} }
function _castKeyToAddr(
uint256 _key
) public pure returns (address _addr) {
_addr = address(uint160(uint256(_key >> 12)));
}
} }

View File

@ -17,22 +17,21 @@ export interface EventAndErrorsInterface extends utils.Interface {
events: { events: {
"AllowedERC20Updated(address,bool)": EventFragment; "AllowedERC20Updated(address,bool)": EventFragment;
"DepositAdded(address,uint256,address,uint256)": EventFragment; "DepositAdded(address,address,uint256)": EventFragment;
"DepositClosed(address,uint256)": EventFragment; "DepositWithdrawn(address,address,uint256)": EventFragment;
"DepositWithdrawn(address,uint256,uint256)": EventFragment;
"FundsWithdrawn(address,uint256)": EventFragment; "FundsWithdrawn(address,uint256)": EventFragment;
"LockAdded(address,bytes32,uint256,uint256)": EventFragment; "LockAdded(address,bytes32,uint256,uint256)": EventFragment;
"LockBlocksUpdated(uint256)": EventFragment; "LockBlocksUpdated(uint256)": EventFragment;
"LockReleased(address,bytes32)": EventFragment; "LockReleased(address,bytes32,uint256)": EventFragment;
"LockReturned(address,bytes32)": EventFragment; "LockReturned(address,bytes32)": EventFragment;
"ReputationUpdated(address)": EventFragment; "ReputationUpdated(address)": EventFragment;
"RootUpdated(address,bytes32)": EventFragment; "RootUpdated(address,bytes32)": EventFragment;
"ValidSet(address,address,bool)": EventFragment;
"ValidSignersUpdated(address[])": EventFragment; "ValidSignersUpdated(address[])": EventFragment;
}; };
getEvent(nameOrSignatureOrTopic: "AllowedERC20Updated"): EventFragment; getEvent(nameOrSignatureOrTopic: "AllowedERC20Updated"): EventFragment;
getEvent(nameOrSignatureOrTopic: "DepositAdded"): EventFragment; getEvent(nameOrSignatureOrTopic: "DepositAdded"): EventFragment;
getEvent(nameOrSignatureOrTopic: "DepositClosed"): EventFragment;
getEvent(nameOrSignatureOrTopic: "DepositWithdrawn"): EventFragment; getEvent(nameOrSignatureOrTopic: "DepositWithdrawn"): EventFragment;
getEvent(nameOrSignatureOrTopic: "FundsWithdrawn"): EventFragment; getEvent(nameOrSignatureOrTopic: "FundsWithdrawn"): EventFragment;
getEvent(nameOrSignatureOrTopic: "LockAdded"): EventFragment; getEvent(nameOrSignatureOrTopic: "LockAdded"): EventFragment;
@ -41,6 +40,7 @@ export interface EventAndErrorsInterface extends utils.Interface {
getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment; getEvent(nameOrSignatureOrTopic: "LockReturned"): EventFragment;
getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment; getEvent(nameOrSignatureOrTopic: "ReputationUpdated"): EventFragment;
getEvent(nameOrSignatureOrTopic: "RootUpdated"): EventFragment; getEvent(nameOrSignatureOrTopic: "RootUpdated"): EventFragment;
getEvent(nameOrSignatureOrTopic: "ValidSet"): EventFragment;
getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment; getEvent(nameOrSignatureOrTopic: "ValidSignersUpdated"): EventFragment;
} }
@ -58,35 +58,23 @@ export type AllowedERC20UpdatedEventFilter =
export interface DepositAddedEventObject { export interface DepositAddedEventObject {
seller: string; seller: string;
depositID: BigNumber;
token: string; token: string;
amount: BigNumber; amount: BigNumber;
} }
export type DepositAddedEvent = TypedEvent< export type DepositAddedEvent = TypedEvent<
[string, BigNumber, string, BigNumber], [string, string, BigNumber],
DepositAddedEventObject DepositAddedEventObject
>; >;
export type DepositAddedEventFilter = TypedEventFilter<DepositAddedEvent>; export type DepositAddedEventFilter = TypedEventFilter<DepositAddedEvent>;
export interface DepositClosedEventObject {
seller: string;
depositID: BigNumber;
}
export type DepositClosedEvent = TypedEvent<
[string, BigNumber],
DepositClosedEventObject
>;
export type DepositClosedEventFilter = TypedEventFilter<DepositClosedEvent>;
export interface DepositWithdrawnEventObject { export interface DepositWithdrawnEventObject {
seller: string; seller: string;
depositID: BigNumber; token: string;
amount: BigNumber; amount: BigNumber;
} }
export type DepositWithdrawnEvent = TypedEvent< export type DepositWithdrawnEvent = TypedEvent<
[string, BigNumber, BigNumber], [string, string, BigNumber],
DepositWithdrawnEventObject DepositWithdrawnEventObject
>; >;
@ -107,7 +95,7 @@ export type FundsWithdrawnEventFilter = TypedEventFilter<FundsWithdrawnEvent>;
export interface LockAddedEventObject { export interface LockAddedEventObject {
buyer: string; buyer: string;
lockID: string; lockID: string;
depositID: BigNumber; seller: BigNumber;
amount: BigNumber; amount: BigNumber;
} }
export type LockAddedEvent = TypedEvent< export type LockAddedEvent = TypedEvent<
@ -131,9 +119,10 @@ export type LockBlocksUpdatedEventFilter =
export interface LockReleasedEventObject { export interface LockReleasedEventObject {
buyer: string; buyer: string;
lockId: string; lockId: string;
amount: BigNumber;
} }
export type LockReleasedEvent = TypedEvent< export type LockReleasedEvent = TypedEvent<
[string, string], [string, string, BigNumber],
LockReleasedEventObject LockReleasedEventObject
>; >;
@ -172,6 +161,18 @@ export type RootUpdatedEvent = TypedEvent<
export type RootUpdatedEventFilter = TypedEventFilter<RootUpdatedEvent>; export type RootUpdatedEventFilter = TypedEventFilter<RootUpdatedEvent>;
export interface ValidSetEventObject {
seller: string;
token: string;
state: boolean;
}
export type ValidSetEvent = TypedEvent<
[string, string, boolean],
ValidSetEventObject
>;
export type ValidSetEventFilter = TypedEventFilter<ValidSetEvent>;
export interface ValidSignersUpdatedEventObject { export interface ValidSignersUpdatedEventObject {
signers: string[]; signers: string[];
} }
@ -223,36 +224,25 @@ export interface EventAndErrors extends BaseContract {
state?: PromiseOrValue<boolean> | null state?: PromiseOrValue<boolean> | null
): AllowedERC20UpdatedEventFilter; ): AllowedERC20UpdatedEventFilter;
"DepositAdded(address,uint256,address,uint256)"( "DepositAdded(address,address,uint256)"(
seller?: PromiseOrValue<string> | null, seller?: PromiseOrValue<string> | null,
depositID?: null,
token?: null, token?: null,
amount?: null amount?: null
): DepositAddedEventFilter; ): DepositAddedEventFilter;
DepositAdded( DepositAdded(
seller?: PromiseOrValue<string> | null, seller?: PromiseOrValue<string> | null,
depositID?: null,
token?: null, token?: null,
amount?: null amount?: null
): DepositAddedEventFilter; ): DepositAddedEventFilter;
"DepositClosed(address,uint256)"( "DepositWithdrawn(address,address,uint256)"(
seller?: PromiseOrValue<string> | null, seller?: PromiseOrValue<string> | null,
depositID?: null token?: null,
): DepositClosedEventFilter;
DepositClosed(
seller?: PromiseOrValue<string> | null,
depositID?: null
): DepositClosedEventFilter;
"DepositWithdrawn(address,uint256,uint256)"(
seller?: PromiseOrValue<string> | null,
depositID?: null,
amount?: null amount?: null
): DepositWithdrawnEventFilter; ): DepositWithdrawnEventFilter;
DepositWithdrawn( DepositWithdrawn(
seller?: PromiseOrValue<string> | null, seller?: PromiseOrValue<string> | null,
depositID?: null, token?: null,
amount?: null amount?: null
): DepositWithdrawnEventFilter; ): DepositWithdrawnEventFilter;
@ -265,26 +255,28 @@ export interface EventAndErrors extends BaseContract {
"LockAdded(address,bytes32,uint256,uint256)"( "LockAdded(address,bytes32,uint256,uint256)"(
buyer?: PromiseOrValue<string> | null, buyer?: PromiseOrValue<string> | null,
lockID?: PromiseOrValue<BytesLike> | null, lockID?: PromiseOrValue<BytesLike> | null,
depositID?: null, seller?: null,
amount?: null amount?: null
): LockAddedEventFilter; ): LockAddedEventFilter;
LockAdded( LockAdded(
buyer?: PromiseOrValue<string> | null, buyer?: PromiseOrValue<string> | null,
lockID?: PromiseOrValue<BytesLike> | null, lockID?: PromiseOrValue<BytesLike> | null,
depositID?: null, seller?: null,
amount?: null amount?: null
): LockAddedEventFilter; ): LockAddedEventFilter;
"LockBlocksUpdated(uint256)"(blocks?: null): LockBlocksUpdatedEventFilter; "LockBlocksUpdated(uint256)"(blocks?: null): LockBlocksUpdatedEventFilter;
LockBlocksUpdated(blocks?: null): LockBlocksUpdatedEventFilter; LockBlocksUpdated(blocks?: null): LockBlocksUpdatedEventFilter;
"LockReleased(address,bytes32)"( "LockReleased(address,bytes32,uint256)"(
buyer?: PromiseOrValue<string> | null, buyer?: PromiseOrValue<string> | null,
lockId?: null lockId?: null,
amount?: null
): LockReleasedEventFilter; ): LockReleasedEventFilter;
LockReleased( LockReleased(
buyer?: PromiseOrValue<string> | null, buyer?: PromiseOrValue<string> | null,
lockId?: null lockId?: null,
amount?: null
): LockReleasedEventFilter; ): LockReleasedEventFilter;
"LockReturned(address,bytes32)"( "LockReturned(address,bytes32)"(
@ -307,6 +299,17 @@ export interface EventAndErrors extends BaseContract {
): RootUpdatedEventFilter; ): RootUpdatedEventFilter;
RootUpdated(seller?: null, merkleRoot?: null): RootUpdatedEventFilter; RootUpdated(seller?: null, merkleRoot?: null): RootUpdatedEventFilter;
"ValidSet(address,address,bool)"(
seller?: PromiseOrValue<string> | null,
token?: null,
state?: null
): ValidSetEventFilter;
ValidSet(
seller?: PromiseOrValue<string> | null,
token?: null,
state?: null
): ValidSetEventFilter;
"ValidSignersUpdated(address[])"( "ValidSignersUpdated(address[])"(
signers?: null signers?: null
): ValidSignersUpdatedEventFilter; ): ValidSignersUpdatedEventFilter;

View File

@ -25,11 +25,21 @@ const _abi = [
name: "AmountNotAllowed", name: "AmountNotAllowed",
type: "error", type: "error",
}, },
{
inputs: [],
name: "DecOverflow",
type: "error",
},
{ {
inputs: [], inputs: [],
name: "DepositAlreadyExists", name: "DepositAlreadyExists",
type: "error", type: "error",
}, },
{
inputs: [],
name: "EmptyPixTarget",
type: "error",
},
{ {
inputs: [], inputs: [],
name: "InvalidDeposit", name: "InvalidDeposit",
@ -55,6 +65,11 @@ const _abi = [
name: "LoopOverflow", name: "LoopOverflow",
type: "error", type: "error",
}, },
{
inputs: [],
name: "MaxBalExceeded",
type: "error",
},
{ {
inputs: [], inputs: [],
name: "NoTokens", name: "NoTokens",
@ -70,6 +85,11 @@ const _abi = [
name: "NotExpired", name: "NotExpired",
type: "error", type: "error",
}, },
{
inputs: [],
name: "NotInitialized",
type: "error",
},
{ {
inputs: [], inputs: [],
name: "OnlySeller", name: "OnlySeller",
@ -118,12 +138,6 @@ const _abi = [
name: "seller", name: "seller",
type: "address", type: "address",
}, },
{
indexed: false,
internalType: "uint256",
name: "depositID",
type: "uint256",
},
{ {
indexed: false, indexed: false,
internalType: "address", internalType: "address",
@ -151,29 +165,10 @@ const _abi = [
}, },
{ {
indexed: false, indexed: false,
internalType: "uint256",
name: "depositID",
type: "uint256",
},
],
name: "DepositClosed",
type: "event",
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address", internalType: "address",
name: "seller", name: "token",
type: "address", type: "address",
}, },
{
indexed: false,
internalType: "uint256",
name: "depositID",
type: "uint256",
},
{ {
indexed: false, indexed: false,
internalType: "uint256", internalType: "uint256",
@ -221,7 +216,7 @@ const _abi = [
{ {
indexed: false, indexed: false,
internalType: "uint256", internalType: "uint256",
name: "depositID", name: "seller",
type: "uint256", type: "uint256",
}, },
{ {
@ -262,6 +257,12 @@ const _abi = [
name: "lockId", name: "lockId",
type: "bytes32", type: "bytes32",
}, },
{
indexed: false,
internalType: "uint256",
name: "amount",
type: "uint256",
},
], ],
name: "LockReleased", name: "LockReleased",
type: "event", type: "event",
@ -317,6 +318,31 @@ const _abi = [
name: "RootUpdated", name: "RootUpdated",
type: "event", type: "event",
}, },
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "seller",
type: "address",
},
{
indexed: false,
internalType: "address",
name: "token",
type: "address",
},
{
indexed: false,
internalType: "bool",
name: "state",
type: "bool",
},
],
name: "ValidSet",
type: "event",
},
{ {
anonymous: false, anonymous: false,
inputs: [ inputs: [

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -36,8 +36,6 @@ describe("Reputation", () => {
expect(tx2).to.eq(curve(500)); expect(tx2).to.eq(curve(500));
expect(tx3).to.eq(curve(444444)); expect(tx3).to.eq(curve(444444));
expect(tx4).to.eq(curve(988700)); expect(tx4).to.eq(curve(988700));
}); });
}); });
}); });

File diff suppressed because it is too large Load Diff