Moved stack allocation from memory to calldata
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
import { ERC20, OwnerSettings } from "./OwnerSettings.sol";
|
||||
import { ERC20, OwnerSettings } from "contracts/core/OwnerSettings.sol";
|
||||
|
||||
import { ECDSA } from "../lib/utils/ECDSA.sol";
|
||||
import { MerkleProofLib as Merkle } from "../lib/utils/MerkleProofLib.sol";
|
||||
import { ReentrancyGuard } from "../lib/utils/ReentrancyGuard.sol";
|
||||
import { ECDSA } from "contracts/lib/utils/ECDSA.sol";
|
||||
import { MerkleProofLib as Merkle } from "contracts/lib/utils/MerkleProofLib.sol";
|
||||
import { ReentrancyGuard } from "contracts/lib/utils/ReentrancyGuard.sol";
|
||||
|
||||
abstract contract BaseUtils is
|
||||
OwnerSettings,
|
||||
@@ -93,7 +93,7 @@ abstract contract BaseUtils is
|
||||
}
|
||||
|
||||
function _setSellerBalance(
|
||||
uint256 _sellerKey,
|
||||
address _sellerKey,
|
||||
ERC20 _erc20,
|
||||
uint256 _packed,
|
||||
bytes32 _pixTarget
|
||||
@@ -101,7 +101,7 @@ abstract contract BaseUtils is
|
||||
assembly {
|
||||
mstore(0x20, _erc20)
|
||||
mstore(0x0c, _SELLER_BALANCE_SLOT_SEED)
|
||||
mstore(0x00, shr(0xc, _sellerKey))
|
||||
mstore(0x00, _sellerKey)
|
||||
let _loc := keccak256(0x0c, 0x34)
|
||||
sstore(add(_loc, 0x01), _packed)
|
||||
sstore(_loc, _pixTarget)
|
||||
@@ -109,55 +109,55 @@ abstract contract BaseUtils is
|
||||
}
|
||||
|
||||
function _setValidState(
|
||||
uint256 _sellerKey,
|
||||
address _sellerKey,
|
||||
ERC20 _erc20,
|
||||
uint256 _packed
|
||||
) internal {
|
||||
assembly {
|
||||
mstore(0x20, _erc20)
|
||||
mstore(0x0c, _SELLER_BALANCE_SLOT_SEED)
|
||||
mstore(0x00, shr(0xc, _sellerKey))
|
||||
mstore(0x00, _sellerKey)
|
||||
let _loc := keccak256(0x0c, 0x34)
|
||||
sstore(add(_loc, 0x01), _packed)
|
||||
}
|
||||
}
|
||||
|
||||
function _addSellerBalance(
|
||||
uint256 _sellerKey,
|
||||
address _sellerKey,
|
||||
ERC20 _erc20,
|
||||
uint256 _amount
|
||||
) internal {
|
||||
assembly {
|
||||
mstore(0x20, _erc20)
|
||||
mstore(0x0c, _SELLER_BALANCE_SLOT_SEED)
|
||||
mstore(0x00, shr(0xc, _sellerKey))
|
||||
mstore(0x00, _sellerKey)
|
||||
let _loc := add(keccak256(0x0c, 0x34), 0x01)
|
||||
sstore(_loc, add(sload(_loc), _amount))
|
||||
}
|
||||
}
|
||||
|
||||
function _decSellerBalance(
|
||||
uint256 _sellerKey,
|
||||
address _sellerKey,
|
||||
ERC20 _erc20,
|
||||
uint256 _amount
|
||||
) internal {
|
||||
assembly {
|
||||
mstore(0x20, _erc20)
|
||||
mstore(0x0c, _SELLER_BALANCE_SLOT_SEED)
|
||||
mstore(0x00, shr(0xc, _sellerKey))
|
||||
mstore(0x00, _sellerKey)
|
||||
let _loc := add(keccak256(0x0c, 0x34), 0x01)
|
||||
sstore(_loc, sub(sload(_loc), _amount))
|
||||
}
|
||||
}
|
||||
|
||||
function __sellerBalance(
|
||||
uint256 _sellerKey,
|
||||
address _sellerKey,
|
||||
ERC20 _erc20
|
||||
) internal view returns (uint256 _packed) {
|
||||
assembly {
|
||||
mstore(0x20, _erc20)
|
||||
mstore(0x0c, _SELLER_BALANCE_SLOT_SEED)
|
||||
mstore(0x00, shr(0xc, _sellerKey))
|
||||
mstore(0x00, _sellerKey)
|
||||
_packed := sload(add(keccak256(0x0c, 0x34), 0x01))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,33 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
import { ERC20 } from "contracts/lib/tokens/ERC20.sol";
|
||||
|
||||
library DataTypes {
|
||||
struct DepositArgs {
|
||||
string pixTarget;
|
||||
bytes32 allowlistRoot;
|
||||
ERC20 token;
|
||||
uint96 amount;
|
||||
bool valid;
|
||||
}
|
||||
|
||||
struct LockArgs {
|
||||
address seller;
|
||||
ERC20 token;
|
||||
uint80 amount;
|
||||
bytes32[] merkleProof;
|
||||
uint256[] expiredLocks;
|
||||
}
|
||||
|
||||
struct Lock {
|
||||
uint256 sellerKey;
|
||||
uint256 counter;
|
||||
uint256 expirationBlock;
|
||||
bytes32 pixTarget;
|
||||
uint80 amount;
|
||||
address token;
|
||||
address buyerAddress;
|
||||
address seller;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
|
||||
@@ -28,7 +28,7 @@ interface EventAndErrors {
|
||||
event LockAdded(
|
||||
address indexed buyer,
|
||||
uint256 indexed lockID,
|
||||
uint256 seller,
|
||||
address seller,
|
||||
uint256 amount
|
||||
);
|
||||
/// @dev 0x364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.19;
|
||||
|
||||
import { ERC2771Context as ERC2771 } from "../lib/metatx/ERC2771Context.sol";
|
||||
import { ERC20, SafeTransferLib } from "../lib/utils/SafeTransferLib.sol";
|
||||
import { IReputation } from "../lib/interfaces/IReputation.sol";
|
||||
import { EventAndErrors } from "./EventAndErrors.sol";
|
||||
import { Constants } from "./Constants.sol";
|
||||
import { Owned } from "../lib/auth/Owned.sol";
|
||||
import { ERC2771Context as ERC2771 } from "contracts/lib/metatx/ERC2771Context.sol";
|
||||
import { ERC20, SafeTransferLib } from "contracts/lib/utils/SafeTransferLib.sol";
|
||||
import { IReputation } from "contracts/lib/interfaces/IReputation.sol";
|
||||
import { EventAndErrors } from "contracts/core/EventAndErrors.sol";
|
||||
import { Constants } from "contracts/core/Constants.sol";
|
||||
import { Owned } from "contracts/lib/auth/Owned.sol";
|
||||
|
||||
abstract contract OwnerSettings is
|
||||
Constants,
|
||||
@@ -121,7 +121,7 @@ abstract contract OwnerSettings is
|
||||
} iszero(returndatasize()) {
|
||||
/* */
|
||||
} {
|
||||
sstore(shl(12, mload(i)), true)
|
||||
sstore(shl(0xc, mload(i)), true)
|
||||
i := add(i, 0x20)
|
||||
|
||||
if iszero(lt(i, end)) {
|
||||
@@ -187,11 +187,11 @@ abstract contract OwnerSettings is
|
||||
}
|
||||
|
||||
function sellerAllowList(
|
||||
uint256 sellerKey
|
||||
address sellerKey
|
||||
) public view returns (bytes32 root) {
|
||||
assembly {
|
||||
mstore(0x0c, _SELLER_ALLOWLIST_SLOT_SEED)
|
||||
mstore(0x00, shr(12, sellerKey))
|
||||
mstore(0x00, sellerKey)
|
||||
root := sload(keccak256(0x00, 0x20))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ pragma solidity 0.8.19;
|
||||
/// |__| |__|
|
||||
///
|
||||
|
||||
import { OwnerSettings, ERC20, SafeTransferLib } from "./core/OwnerSettings.sol";
|
||||
import { BaseUtils } from "./core/BaseUtils.sol";
|
||||
import { DataTypes as DT } from "./core/DataTypes.sol";
|
||||
import { OwnerSettings, ERC20, SafeTransferLib } from "contracts/core/OwnerSettings.sol";
|
||||
import { BaseUtils } from "contracts/core/BaseUtils.sol";
|
||||
import { DataTypes as DT } from "contracts/core/DataTypes.sol";
|
||||
|
||||
|
||||
contract P2PIX is BaseUtils {
|
||||
@@ -18,6 +18,8 @@ contract P2PIX is BaseUtils {
|
||||
// solhint-disable no-inline-assembly
|
||||
// solhint-disable no-empty-blocks
|
||||
|
||||
using DT for DT.DepositArgs;
|
||||
using DT for DT.LockArgs;
|
||||
using DT for DT.Lock;
|
||||
using DT for DT.LockStatus;
|
||||
|
||||
@@ -53,55 +55,49 @@ contract P2PIX is BaseUtils {
|
||||
/// @notice Creates a deposit order based on a seller's
|
||||
/// offer of an amount of ERC20 tokens.
|
||||
/// @dev Seller needs to send his tokens to the P2PIX smart contract.
|
||||
/// @param _pixTarget Pix key destination provided by the offer's seller.
|
||||
/// @param allowlistRoot Optional allow list merkleRoot update `bytes32` value.
|
||||
/// as the deposit identifier.
|
||||
/* /// @param _pixTarget Pix key destination provided by the offer's seller. */
|
||||
/* /// @param allowlistRoot Optional allow list merkleRoot update `bytes32` value. */
|
||||
/* /// as the deposit identifier. */
|
||||
/// @dev Function sighash: 0xbfe07da6.
|
||||
function deposit(
|
||||
address _token,
|
||||
uint96 _amount,
|
||||
string memory _pixTarget,
|
||||
bool _valid,
|
||||
bytes32 allowlistRoot
|
||||
DT.DepositArgs calldata args
|
||||
) public {
|
||||
ERC20 t = ERC20(_token);
|
||||
uint256 k = _castAddrToKey(msg.sender);
|
||||
|
||||
if (bytes(_pixTarget).length == 0) revert EmptyPixTarget();
|
||||
if (!allowedERC20s(t)) revert TokenDenied();
|
||||
uint256 _sellerBalance = __sellerBalance(k,t);
|
||||
if (bytes(args.pixTarget).length == 0) revert EmptyPixTarget();
|
||||
if (!allowedERC20s(args.token)) revert TokenDenied();
|
||||
uint256 _sellerBalance = __sellerBalance(msg.sender, args.token);
|
||||
|
||||
uint256 currBal = _sellerBalance & BITMASK_SB_ENTRY;
|
||||
uint256 _newBal = uint256(currBal + _amount);
|
||||
uint256 _newBal = uint256(currBal + args.amount);
|
||||
if (_newBal > MAXBALANCE_UPPERBOUND)
|
||||
revert MaxBalExceeded();
|
||||
|
||||
setReentrancyGuard();
|
||||
|
||||
if (allowlistRoot != 0) {
|
||||
setRoot(msg.sender, allowlistRoot);
|
||||
if (args.allowlistRoot != 0) {
|
||||
setRoot(msg.sender, args.allowlistRoot);
|
||||
}
|
||||
|
||||
bytes32 pixTargetCasted = getStr(_pixTarget);
|
||||
uint256 validCasted = _castBool(_valid);
|
||||
bytes32 pixTargetCasted = getStr(args.pixTarget);
|
||||
uint256 validCasted = _castBool(args.valid);
|
||||
|
||||
_setSellerBalance(
|
||||
k,
|
||||
t,
|
||||
msg.sender,
|
||||
args.token,
|
||||
(_newBal | (validCasted << BITPOS_VALID)),
|
||||
pixTargetCasted
|
||||
);
|
||||
|
||||
SafeTransferLib.safeTransferFrom(
|
||||
t,
|
||||
args.token,
|
||||
msg.sender,
|
||||
address(this),
|
||||
_amount
|
||||
args.amount
|
||||
);
|
||||
|
||||
clearReentrancyGuard();
|
||||
|
||||
emit DepositAdded(msg.sender, _token, _amount);
|
||||
emit DepositAdded(msg.sender, address(args.token), args.amount);
|
||||
}
|
||||
|
||||
/// @notice Enables seller to invalidate future
|
||||
@@ -109,8 +105,7 @@ contract P2PIX is BaseUtils {
|
||||
/// @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 _sellerBalance = __sellerBalance(msg.sender, token);
|
||||
|
||||
if (_sellerBalance != 0) {
|
||||
uint256 _valid = _castBool(state);
|
||||
@@ -119,7 +114,7 @@ contract P2PIX is BaseUtils {
|
||||
(_sellerBalance & BITMASK_SB_ENTRY) |
|
||||
(_valid << BITPOS_VALID);
|
||||
|
||||
_setValidState(key, token, _sellerBalance);
|
||||
_setValidState(msg.sender, token, _sellerBalance);
|
||||
|
||||
emit ValidSet(msg.sender, address(token), state);
|
||||
} else revert NotInitialized();
|
||||
@@ -127,78 +122,73 @@ contract P2PIX is BaseUtils {
|
||||
|
||||
/// @notice Public method designed to lock an remaining amount of
|
||||
/// the deposit order of a seller.
|
||||
/// @dev Transaction forwarding must leave `merkleProof` empty;
|
||||
/// otherwise, the trustedForwarder must be previously added
|
||||
/// to a seller whitelist.
|
||||
/// @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;
|
||||
/// @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.
|
||||
/// @param _amount The deposit's remaining amount wished to be locked.
|
||||
/// @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
|
||||
/// provided so to unexpire locks using this transaction gas push.
|
||||
/* /// @param _amount The deposit's remaining amount wished to be locked. */
|
||||
/* /// @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 */
|
||||
/* /// provided so to unexpire locks using this transaction gas push. */
|
||||
/// @return lockID The `bytes32` value returned as the lock identifier.
|
||||
/// @dev Function sighash: 0x03aaf306.
|
||||
function lock(
|
||||
address _seller,
|
||||
address _token,
|
||||
uint80 _amount,
|
||||
bytes32[] calldata merkleProof,
|
||||
uint256[] calldata expiredLocks
|
||||
DT.LockArgs calldata args
|
||||
) public nonReentrant returns (uint256 lockID) {
|
||||
unlockExpired(expiredLocks);
|
||||
unlockExpired(args.expiredLocks);
|
||||
|
||||
ERC20 t = ERC20(_token);
|
||||
if (!getValid(_seller, t)) revert InvalidDeposit();
|
||||
if (!getValid(args.seller, args.token)) revert InvalidDeposit();
|
||||
|
||||
uint256 bal = getBalance(_seller, t);
|
||||
if (bal < _amount) revert NotEnoughTokens();
|
||||
uint256 bal = getBalance(args.seller, args.token);
|
||||
if (bal < args.amount) revert NotEnoughTokens();
|
||||
|
||||
uint256 k = _castAddrToKey(_seller);
|
||||
|
||||
uint256 cCounter = lockCounter + 1;
|
||||
uint256 c = lockCounter + 1;
|
||||
|
||||
if (
|
||||
mapLocks[cCounter].expirationBlock >= block.number
|
||||
mapLocks[c].expirationBlock >= block.number
|
||||
) revert NotExpired();
|
||||
|
||||
address sender; uint256 forwarder;
|
||||
(sender, forwarder) = _isTrustedForwarder();
|
||||
bytes32 _pixTarget = getPixTarget(args.seller, args.token);
|
||||
|
||||
DT.Lock memory l = DT.Lock(
|
||||
k,
|
||||
cCounter,
|
||||
c,
|
||||
(block.number + defaultLockBlocks),
|
||||
getPixTarget(_seller, t),
|
||||
_amount,
|
||||
address(t),
|
||||
sender
|
||||
_pixTarget,
|
||||
args.amount,
|
||||
address(args.token),
|
||||
sender,
|
||||
args.seller
|
||||
);
|
||||
|
||||
// transaction forwarding must leave `merkleProof` empty;
|
||||
// otherwise, the trustedForwarder must be previously added
|
||||
// to a seller whitelist.
|
||||
if (merkleProof.length != 0) {
|
||||
_merkleVerify(merkleProof, sellerAllowList(k), sender);
|
||||
lockID = _addLock(bal, _amount, cCounter, l, t, k);
|
||||
if (args.merkleProof.length != 0) {
|
||||
_merkleVerify(args.merkleProof, sellerAllowList(args.seller), sender);
|
||||
lockID = _addLock(bal, l);
|
||||
|
||||
} else {
|
||||
if (l.amount <= REPUTATION_LOWERBOUND) {
|
||||
lockID = _addLock(bal, _amount, cCounter, l, t, k);
|
||||
lockID = _addLock(bal, l);
|
||||
|
||||
} else {
|
||||
if (forwarder != 0) {
|
||||
lockID = _addLock(bal, _amount, cCounter, l, t, k);
|
||||
lockID = _addLock(bal, l);
|
||||
} else {
|
||||
uint256 userCredit = userRecord[_castAddrToKey(msg.sender)];
|
||||
uint256 spendLimit; (spendLimit) = _limiter(userCredit / WAD);
|
||||
uint256 spendLimit; uint256 userCredit =
|
||||
userRecord[_castAddrToKey(msg.sender)];
|
||||
(spendLimit) = _limiter(userCredit / WAD);
|
||||
if (
|
||||
l.amount > (spendLimit * WAD) ||
|
||||
l.amount > LOCKAMOUNT_UPPERBOUND
|
||||
) revert AmountNotAllowed();
|
||||
lockID = _addLock(bal, _amount, cCounter, l, t, k);
|
||||
lockID = _addLock(bal, l);
|
||||
|
||||
/* */}/* */}/* */}
|
||||
}
|
||||
@@ -285,12 +275,12 @@ contract P2PIX is BaseUtils {
|
||||
_notExpired(l);
|
||||
|
||||
uint256 _sellerBalance =
|
||||
__sellerBalance(l.sellerKey, ERC20(l.token)) & BITMASK_SB_ENTRY;
|
||||
__sellerBalance(l.seller, ERC20(l.token)) & BITMASK_SB_ENTRY;
|
||||
|
||||
if ((_sellerBalance + l.amount) > MAXBALANCE_UPPERBOUND)
|
||||
revert MaxBalExceeded();
|
||||
|
||||
_addSellerBalance(l.sellerKey, ERC20(l.token), l.amount);
|
||||
_addSellerBalance(l.seller, ERC20(l.token), l.amount);
|
||||
|
||||
l.amount = 0;
|
||||
|
||||
@@ -335,12 +325,11 @@ contract P2PIX is BaseUtils {
|
||||
if (getValid(msg.sender, token))
|
||||
setValidState(token, false);
|
||||
|
||||
uint256 key = _castAddrToKey(msg.sender);
|
||||
_decBal(
|
||||
(__sellerBalance(key, token) & BITMASK_SB_ENTRY),
|
||||
(__sellerBalance(msg.sender, token) & BITMASK_SB_ENTRY),
|
||||
amount,
|
||||
token,
|
||||
key
|
||||
msg.sender
|
||||
);
|
||||
|
||||
// safeTransfer tokens to seller
|
||||
@@ -400,22 +389,18 @@ contract P2PIX is BaseUtils {
|
||||
|
||||
function _addLock(
|
||||
uint256 _bal,
|
||||
uint256 _amount,
|
||||
uint256 _lockID,
|
||||
DT.Lock memory _l,
|
||||
ERC20 _t,
|
||||
uint256 _k
|
||||
DT.Lock memory _l
|
||||
) internal returns(uint256 counter){
|
||||
mapLocks[_lockID] = _l;
|
||||
mapLocks[_l.counter] = _l;
|
||||
|
||||
_decBal(_bal, _amount, _t, _k);
|
||||
_decBal(_bal, _l.amount, ERC20(_l.token), _l.seller);
|
||||
++lockCounter;
|
||||
counter = _lockID;
|
||||
counter = _l.counter;
|
||||
|
||||
emit LockAdded(
|
||||
_l.buyerAddress,
|
||||
_lockID,
|
||||
_l.sellerKey,
|
||||
_l.counter,
|
||||
_l.seller,
|
||||
_l.amount
|
||||
);
|
||||
}
|
||||
@@ -424,7 +409,7 @@ contract P2PIX is BaseUtils {
|
||||
uint256 _bal,
|
||||
uint256 _amount,
|
||||
ERC20 _t,
|
||||
uint256 _k
|
||||
address _k
|
||||
) private {
|
||||
assembly {
|
||||
if iszero(
|
||||
@@ -561,7 +546,7 @@ contract P2PIX is BaseUtils {
|
||||
);
|
||||
unchecked {
|
||||
for (c; c < len; ) {
|
||||
if (mapLocks[ids[c]].sellerKey == 0x0) {
|
||||
if (mapLocks[ids[c]].seller == address(0)) {
|
||||
sortedIDs[c] = ids[c];
|
||||
status[c] = type(DT.LockStatus).min;
|
||||
++c;
|
||||
|
||||
Reference in New Issue
Block a user