From ed3d000445287d40e1e12e0de8c28425acaf3f23 Mon Sep 17 00:00:00 2001 From: byshape Date: Tue, 19 Dec 2023 18:23:59 +0000 Subject: [PATCH 1/7] Validated idea of inheriting from the limit order settlement basic extension --- contracts/EscrowFactory.sol | 46 +- .../flatten/BasicSettlementExtension.sol | 1118 +++++++++++++++++ contracts/interfaces/IEscrowFactory.sol | 1 - test/EscrowFactory.js | 2 +- test/helpers/escrowUtils.js | 6 +- yarn.lock | 18 +- 6 files changed, 1164 insertions(+), 27 deletions(-) create mode 100644 contracts/flatten/BasicSettlementExtension.sol diff --git a/contracts/EscrowFactory.sol b/contracts/EscrowFactory.sol index cac18b6..4175534 100644 --- a/contracts/EscrowFactory.sol +++ b/contracts/EscrowFactory.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.23; -import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; +// import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; @@ -12,29 +12,26 @@ import { ClonesWithImmutableArgs } from "clones-with-immutable-args/ClonesWithIm import { IEscrowFactory } from "./interfaces/IEscrowFactory.sol"; import { EscrowRegistry } from "./EscrowRegistry.sol"; -contract EscrowFactory is IEscrowFactory { +// TODO: import from the package +import { BasicSettlementExtension, IOrderMixin } from "./flatten/BasicSettlementExtension.sol"; + +contract EscrowFactory is IEscrowFactory, BasicSettlementExtension { using AddressLib for Address; using ClonesWithImmutableArgs for address; using SafeERC20 for IERC20; address public immutable IMPLEMENTATION; - address public immutable LIMIT_ORDER_PROTOCOL; - - /// @dev Modifier to check if the caller is the limit order protocol contract. - modifier onlyLimitOrderProtocol { - if (msg.sender != address(LIMIT_ORDER_PROTOCOL)) revert OnlyLimitOrderProtocol(); - _; - } - constructor(address implementation, address limitOrderProtocol) { + constructor(address implementation, IOrderMixin limitOrderProtocol, IERC20 token) + BasicSettlementExtension(limitOrderProtocol, token) + { IMPLEMENTATION = implementation; - LIMIT_ORDER_PROTOCOL = limitOrderProtocol; } /** * @dev Creates a new escrow contract for maker. */ - function postInteraction( + function _postInteraction( IOrderMixin.Order calldata order, bytes calldata /* extension */, bytes32 orderHash, @@ -43,7 +40,24 @@ contract EscrowFactory is IEscrowFactory { uint256 takingAmount, uint256 /* remainingMakingAmount */, bytes calldata extraData - ) external onlyLimitOrderProtocol { + ) internal override { + ( + uint256 resolverFee, + address integrator, + uint256 integrationFee, + bytes calldata dataReturned + ) = _parseFeeData(extraData, order.makingAmount, makingAmount, takingAmount); + + bytes calldata extraDataParams = dataReturned[:320]; + bytes calldata whitelist = dataReturned[320:]; + + if (!_isWhitelisted(whitelist, taker)) revert ResolverIsNotWhitelisted(); + + _chargeFee(taker, resolverFee); + if (integrationFee > 0) { + IERC20(order.takerAsset.get()).safeTransferFrom(taker, integrator, integrationFee); + } + bytes memory interactionParams = abi.encode( order.maker, taker, @@ -55,7 +69,7 @@ contract EscrowFactory is IEscrowFactory { bytes memory data = abi.encodePacked( block.timestamp, // deployedAt interactionParams, - extraData + extraDataParams ); // Salt is orderHash address escrow = ClonesWithImmutableArgs.addressOfClone3(orderHash); @@ -96,4 +110,8 @@ contract EscrowFactory is IEscrowFactory { ) private returns (EscrowRegistry clone) { clone = EscrowRegistry(IMPLEMENTATION.clone3(data, salt)); } + + function _isWhitelisted(bytes calldata /* whitelist */, address /* resolver */) internal view override returns (bool) { + return true; + } } diff --git a/contracts/flatten/BasicSettlementExtension.sol b/contracts/flatten/BasicSettlementExtension.sol new file mode 100644 index 0000000..b9bde5b --- /dev/null +++ b/contracts/flatten/BasicSettlementExtension.sol @@ -0,0 +1,1118 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.23; + +interface IFeeBank { + /** + * @notice Returns the available credit for a given account in the FeeBank contract. + * @param account The address of the account for which the available credit is being queried. + * @return availableCredit The available credit of the queried account. + */ + function availableCredit(address account) external view returns (uint256 availableCredit); + + /** + * @notice Increases the caller's available credit by the specified amount. + * @param amount The amount of credit to be added to the caller's account. + * @return totalAvailableCredit The updated available credit of the caller's account. + */ + function deposit(uint256 amount) external returns (uint256 totalAvailableCredit); + + /** + * @notice Increases the specified account's available credit by the specified amount. + * @param account The address of the account for which the available credit is being increased. + * @param amount The amount of credit to be added to the account. + * @return totalAvailableCredit The updated available credit of the specified account. + */ + function depositFor(address account, uint256 amount) external returns (uint256 totalAvailableCredit); + + /** + * @notice Increases the caller's available credit by a specified amount with permit. + * @param amount The amount of credit to be added to the caller's account. + * @param permit The permit data authorizing the transaction. + * @return totalAvailableCredit The updated available credit of the caller's account. + */ + function depositWithPermit(uint256 amount, bytes calldata permit) external returns (uint256 totalAvailableCredit); + + /** + * @notice Increases the specified account's available credit by a specified amount with permit. + * @param account The address of the account for which the available credit is being increased. + * @param amount The amount of credit to be added to the account. + * @param permit The permit data authorizing the transaction. + * @return totalAvailableCredit The updated available credit of the specified account. + */ + function depositForWithPermit(address account, uint256 amount, bytes calldata permit) external returns (uint256 totalAvailableCredit); + + /** + * @notice Withdraws a specified amount of credit from the caller's account. + * @param amount The amount of credit to be withdrawn from the caller's account. + * @return totalAvailableCredit The updated available credit of the caller's account. + */ + function withdraw(uint256 amount) external returns (uint256 totalAvailableCredit); + + /** + * @notice Withdraws a specified amount of credit to the specified account. + * @param account The address of the account to which the credit is being withdrawn. + * @param amount The amount of credit to be withdrawn. + * @return totalAvailableCredit The updated available credit of the caller's account. + */ + function withdrawTo(address account, uint256 amount) external returns (uint256 totalAvailableCredit); +} + +////import { IFeeBank } from "./IFeeBank.sol"; + +interface IFeeBankCharger { + /** + * @notice Returns the instance of the FeeBank contract. + * @return The instance of the FeeBank contract. + */ + function feeBank() external view returns (IFeeBank); + + /** + * @notice Returns the available credit for a given account. + * @param account The address of the account for which the available credit is being queried. + * @return The available credit of the queried account. + */ + function availableCredit(address account) external view returns (uint256); + + /** + * @notice Increases the available credit of a given account by a specified amount. + * @param account The address of the account for which the available credit is being increased. + * @param amount The amount by which the available credit will be increased. + * @return allowance The updated available credit of the specified account. + */ + function increaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance); + + /** + * @notice Decreases the available credit of a given account by a specified amount. + * @param account The address of the account for which the available credit is being decreased. + * @param amount The amount by which the available credit will be decreased. + * @return allowance The updated available credit of the specified account. + */ + function decreaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance); +} + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +////import { IFeeBankCharger } from "./interfaces/IFeeBankCharger.sol"; +////import { IFeeBank } from "./interfaces/IFeeBank.sol"; + +/** + * @title FeeBank + * @notice FeeBank contract introduces a credit system for paying fees. + * A user can deposit tokens to the FeeBank contract, obtain credits and then use them to pay fees. + * @dev FeeBank is coupled with FeeBankCharger to actually charge fees. + */ +contract FeeBank is IFeeBank, Ownable { + using SafeERC20 for IERC20; + + error ZeroAddress(); + + IERC20 private immutable _token; + IFeeBankCharger private immutable _charger; + + mapping(address account => uint256 availableCredit) private _accountDeposits; + + constructor(IFeeBankCharger charger_, IERC20 inch_, address owner_) Ownable(owner_) { + if (address(inch_) == address(0)) revert ZeroAddress(); + _charger = charger_; + _token = inch_; + } + + /** + * @notice See {IFeeBank-availableCredit}. + */ + function availableCredit(address account) external view returns (uint256) { + return _charger.availableCredit(account); + } + + /** + * @notice See {IFeeBank-deposit}. + */ + function deposit(uint256 amount) external returns (uint256) { + return _depositFor(msg.sender, amount); + } + + /** + * @notice See {IFeeBank-depositFor}. + */ + function depositFor(address account, uint256 amount) external returns (uint256) { + return _depositFor(account, amount); + } + + /** + * @notice See {IFeeBank-depositWithPermit}. + */ + function depositWithPermit(uint256 amount, bytes calldata permit) external returns (uint256) { + return depositForWithPermit(msg.sender, amount, permit); + } + + /** + * @notice See {IFeeBank-depositForWithPermit}. + */ + function depositForWithPermit( + address account, + uint256 amount, + bytes calldata permit + ) public returns (uint256) { + _token.safePermit(permit); + return _depositFor(account, amount); + } + + /** + * @notice See {IFeeBank-withdraw}. + */ + function withdraw(uint256 amount) external returns (uint256) { + return _withdrawTo(msg.sender, amount); + } + + /** + * @notice See {IFeeBank-withdrawTo}. + */ + function withdrawTo(address account, uint256 amount) external returns (uint256) { + return _withdrawTo(account, amount); + } + + /** + * @notice Admin method returns commissions spent by users. + * @param accounts Accounts whose commissions are being withdrawn. + * @return totalAccountFees The total amount of accounts commissions. + */ + function gatherFees(address[] calldata accounts) external onlyOwner returns (uint256 totalAccountFees) { + uint256 accountsLength = accounts.length; + unchecked { + for (uint256 i = 0; i < accountsLength; ++i) { + address account = accounts[i]; + uint256 accountDeposit = _accountDeposits[account]; + uint256 availableCredit_ = _charger.availableCredit(account); + _accountDeposits[account] = availableCredit_; + totalAccountFees += accountDeposit - availableCredit_; // overflow is impossible due to checks in FeeBankCharger + } + } + _token.safeTransfer(msg.sender, totalAccountFees); + } + + function _depositFor(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) { + if (account == address(0)) revert ZeroAddress(); + _token.safeTransferFrom(msg.sender, address(this), amount); + unchecked { + _accountDeposits[account] += amount; // overflow is impossible due to limited _token supply + } + totalAvailableCredit = _charger.increaseAvailableCredit(account, amount); + } + + function _withdrawTo(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) { + totalAvailableCredit = _charger.decreaseAvailableCredit(msg.sender, amount); + unchecked { + _accountDeposits[msg.sender] -= amount; // underflow is impossible due to checks in FeeBankCharger + } + _token.safeTransfer(account, amount); + } +} + +type TakerTraits is uint256; + +/** + * @title TakerTraitsLib + * @notice This library to manage and check TakerTraits, which are used to encode the taker's preferences for an order in a single uint256. + * @dev The TakerTraits are structured as follows: + * High bits are used for flags + * 255 bit `_MAKER_AMOUNT_FLAG` - If set, the taking amount is calculated based on making amount, otherwise making amount is calculated based on taking amount. + * 254 bit `_UNWRAP_WETH_FLAG` - If set, the WETH will be unwrapped into ETH before sending to taker. + * 253 bit `_SKIP_ORDER_PERMIT_FLAG` - If set, the order skips maker's permit execution. + * 252 bit `_USE_PERMIT2_FLAG` - If set, the order uses the permit2 function for authorization. + * The remaining bits are used to store the threshold amount (the maximum amount a taker agrees to give in exchange for a making amount). + */ +library TakerTraitsLib { + uint256 private constant _MAKER_AMOUNT_FLAG = 1 << 255; + uint256 private constant _UNWRAP_WETH_FLAG = 1 << 254; + uint256 private constant _SKIP_ORDER_PERMIT_FLAG = 1 << 253; + uint256 private constant _USE_PERMIT2_FLAG = 1 << 252; + uint256 private constant _ARGS_HAS_TARGET = 1 << 251; + + uint256 private constant _ARGS_EXTENSION_LENGTH_OFFSET = 224; + uint256 private constant _ARGS_EXTENSION_LENGTH_MASK = 0xffffff; + uint256 private constant _ARGS_INTERACTION_LENGTH_OFFSET = 200; + uint256 private constant _ARGS_INTERACTION_LENGTH_MASK = 0xffffff; + + uint256 private constant _AMOUNT_MASK = 0x000000000000000000ffffffffffffffffffffffffffffffffffffffffffffff; + + function argsHasTarget(TakerTraits takerTraits) internal pure returns (bool) { + return (TakerTraits.unwrap(takerTraits) & _ARGS_HAS_TARGET) != 0; + } + + function argsExtensionLength(TakerTraits takerTraits) internal pure returns (uint256) { + return (TakerTraits.unwrap(takerTraits) >> _ARGS_EXTENSION_LENGTH_OFFSET) & _ARGS_EXTENSION_LENGTH_MASK; + } + + function argsInteractionLength(TakerTraits takerTraits) internal pure returns (uint256) { + return (TakerTraits.unwrap(takerTraits) >> _ARGS_INTERACTION_LENGTH_OFFSET) & _ARGS_INTERACTION_LENGTH_MASK; + } + + /** + * @notice Checks if the taking amount should be calculated based on making amount. + * @param takerTraits The traits of the taker. + * @return result A boolean indicating whether the taking amount should be calculated based on making amount. + */ + function isMakingAmount(TakerTraits takerTraits) internal pure returns (bool) { + return (TakerTraits.unwrap(takerTraits) & _MAKER_AMOUNT_FLAG) != 0; + } + + /** + * @notice Checks if the order should unwrap WETH and send ETH to taker. + * @param takerTraits The traits of the taker. + * @return result A boolean indicating whether the order should unwrap WETH. + */ + function unwrapWeth(TakerTraits takerTraits) internal pure returns (bool) { + return (TakerTraits.unwrap(takerTraits) & _UNWRAP_WETH_FLAG) != 0; + } + + /** + * @notice Checks if the order should skip maker's permit execution. + * @param takerTraits The traits of the taker. + * @return result A boolean indicating whether the order don't apply permit. + */ + function skipMakerPermit(TakerTraits takerTraits) internal pure returns (bool) { + return (TakerTraits.unwrap(takerTraits) & _SKIP_ORDER_PERMIT_FLAG) != 0; + } + + /** + * @notice Checks if the order uses the permit2 instead of permit. + * @param takerTraits The traits of the taker. + * @return result A boolean indicating whether the order uses the permit2. + */ + function usePermit2(TakerTraits takerTraits) internal pure returns (bool) { + return (TakerTraits.unwrap(takerTraits) & _USE_PERMIT2_FLAG) != 0; + } + + /** + * @notice Retrieves the threshold amount from the takerTraits. + * The maximum amount a taker agrees to give in exchange for a making amount. + * @param takerTraits The traits of the taker. + * @return result The threshold amount encoded in the takerTraits. + */ + function threshold(TakerTraits takerTraits) internal pure returns (uint256) { + return TakerTraits.unwrap(takerTraits) & _AMOUNT_MASK; + } +} + +type MakerTraits is uint256; + +/** + * @title MakerTraitsLib + * @notice A library to manage and check MakerTraits, which are used to encode the maker's preferences for an order in a single uint256. + * @dev + * The MakerTraits type is a uint256 and different parts of the number are used to encode different traits. + * High bits are used for flags + * 255 bit `NO_PARTIAL_FILLS_FLAG` - if set, the order does not allow partial fills + * 254 bit `ALLOW_MULTIPLE_FILLS_FLAG` - if set, the order permits multiple fills + * 252 bit `PRE_INTERACTION_CALL_FLAG` - if set, the order requires pre-interaction call + * 251 bit `POST_INTERACTION_CALL_FLAG` - if set, the order requires post-interaction call + * 250 bit `NEED_CHECK_EPOCH_MANAGER_FLAG` - if set, the order requires to check the epoch manager + * 249 bit `HAS_EXTENSION_FLAG` - if set, the order has extension(s) + * 248 bit `USE_PERMIT2_FLAG` - if set, the order uses permit2 + * 247 bit `UNWRAP_WETH_FLAG` - if set, the order requires to unwrap WETH + + * Low 200 bits are used for allowed sender, expiration, nonceOrEpoch, and series + * uint80 last 10 bytes of allowed sender address (0 if any) + * uint40 expiration timestamp (0 if none) + * uint40 nonce or epoch + * uint40 series + */ +library MakerTraitsLib { + // Low 200 bits are used for allowed sender, expiration, nonceOrEpoch, and series + uint256 private constant _ALLOWED_SENDER_MASK = type(uint80).max; + uint256 private constant _EXPIRATION_OFFSET = 80; + uint256 private constant _EXPIRATION_MASK = type(uint40).max; + uint256 private constant _NONCE_OR_EPOCH_OFFSET = 120; + uint256 private constant _NONCE_OR_EPOCH_MASK = type(uint40).max; + uint256 private constant _SERIES_OFFSET = 160; + uint256 private constant _SERIES_MASK = type(uint40).max; + + uint256 private constant _NO_PARTIAL_FILLS_FLAG = 1 << 255; + uint256 private constant _ALLOW_MULTIPLE_FILLS_FLAG = 1 << 254; + uint256 private constant _PRE_INTERACTION_CALL_FLAG = 1 << 252; + uint256 private constant _POST_INTERACTION_CALL_FLAG = 1 << 251; + uint256 private constant _NEED_CHECK_EPOCH_MANAGER_FLAG = 1 << 250; + uint256 private constant _HAS_EXTENSION_FLAG = 1 << 249; + uint256 private constant _USE_PERMIT2_FLAG = 1 << 248; + uint256 private constant _UNWRAP_WETH_FLAG = 1 << 247; + + /** + * @notice Checks if the order has the extension flag set. + * @dev If the `HAS_EXTENSION_FLAG` is set in the makerTraits, then the protocol expects that the order has extension(s). + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the flag is set. + */ + function hasExtension(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _HAS_EXTENSION_FLAG) != 0; + } + + /** + * @notice Checks if the maker allows a specific taker to fill the order. + * @param makerTraits The traits of the maker. + * @param sender The address of the taker to be checked. + * @return result A boolean indicating whether the taker is allowed. + */ + function isAllowedSender(MakerTraits makerTraits, address sender) internal pure returns (bool) { + uint160 allowedSender = uint160(MakerTraits.unwrap(makerTraits) & _ALLOWED_SENDER_MASK); + return allowedSender == 0 || allowedSender == uint160(sender) & _ALLOWED_SENDER_MASK; + } + + /** + * @notice Checks if the order has expired. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the order has expired. + */ + function isExpired(MakerTraits makerTraits) internal view returns (bool) { + uint256 expiration = (MakerTraits.unwrap(makerTraits) >> _EXPIRATION_OFFSET) & _EXPIRATION_MASK; + return expiration != 0 && expiration < block.timestamp; // solhint-disable-line not-rely-on-time + } + + /** + * @notice Returns the nonce or epoch of the order. + * @param makerTraits The traits of the maker. + * @return result The nonce or epoch of the order. + */ + function nonceOrEpoch(MakerTraits makerTraits) internal pure returns (uint256) { + return (MakerTraits.unwrap(makerTraits) >> _NONCE_OR_EPOCH_OFFSET) & _NONCE_OR_EPOCH_MASK; + } + + /** + * @notice Returns the series of the order. + * @param makerTraits The traits of the maker. + * @return result The series of the order. + */ + function series(MakerTraits makerTraits) internal pure returns (uint256) { + return (MakerTraits.unwrap(makerTraits) >> _SERIES_OFFSET) & _SERIES_MASK; + } + + /** + * @notice Determines if the order allows partial fills. + * @dev If the _NO_PARTIAL_FILLS_FLAG is not set in the makerTraits, then the order allows partial fills. + * @param makerTraits The traits of the maker, determining their preferences for the order. + * @return result A boolean indicating whether the maker allows partial fills. + */ + function allowPartialFills(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _NO_PARTIAL_FILLS_FLAG) == 0; + } + + /** + * @notice Checks if the maker needs pre-interaction call. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the maker needs a pre-interaction call. + */ + function needPreInteractionCall(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _PRE_INTERACTION_CALL_FLAG) != 0; + } + + /** + * @notice Checks if the maker needs post-interaction call. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the maker needs a post-interaction call. + */ + function needPostInteractionCall(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _POST_INTERACTION_CALL_FLAG) != 0; + } + + /** + * @notice Determines if the order allows multiple fills. + * @dev If the _ALLOW_MULTIPLE_FILLS_FLAG is set in the makerTraits, then the maker allows multiple fills. + * @param makerTraits The traits of the maker, determining their preferences for the order. + * @return result A boolean indicating whether the maker allows multiple fills. + */ + function allowMultipleFills(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _ALLOW_MULTIPLE_FILLS_FLAG) != 0; + } + + /** + * @notice Determines if an order should use the bit invalidator or remaining amount validator. + * @dev The bit invalidator can be used if the order does not allow partial or multiple fills. + * @param makerTraits The traits of the maker, determining their preferences for the order. + * @return result A boolean indicating whether the bit invalidator should be used. + * True if the order requires the use of the bit invalidator. + */ + function useBitInvalidator(MakerTraits makerTraits) internal pure returns (bool) { + return !allowPartialFills(makerTraits) || !allowMultipleFills(makerTraits); + } + + /** + * @notice Checks if the maker needs to check the epoch. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the maker needs to check the epoch manager. + */ + function needCheckEpochManager(MakerTraits makerTraits) internal pure returns (bool) { + return (MakerTraits.unwrap(makerTraits) & _NEED_CHECK_EPOCH_MANAGER_FLAG) != 0; + } + + /** + * @notice Checks if the maker uses permit2. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the maker uses permit2. + */ + function usePermit2(MakerTraits makerTraits) internal pure returns (bool) { + return MakerTraits.unwrap(makerTraits) & _USE_PERMIT2_FLAG != 0; + } + + /** + * @notice Checks if the maker needs to unwraps WETH. + * @param makerTraits The traits of the maker. + * @return result A boolean indicating whether the maker needs to unwrap WETH. + */ + function unwrapWeth(MakerTraits makerTraits) internal pure returns (bool) { + return MakerTraits.unwrap(makerTraits) & _UNWRAP_WETH_FLAG != 0; + } +} + +import "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; +////import "../libraries/MakerTraitsLib.sol"; +////import "../libraries/TakerTraitsLib.sol"; + +interface IOrderMixin { + struct Order { + uint256 salt; + Address maker; + Address receiver; + Address makerAsset; + Address takerAsset; + uint256 makingAmount; + uint256 takingAmount; + MakerTraits makerTraits; + } + + error InvalidatedOrder(); + error TakingAmountExceeded(); + error PrivateOrder(); + error BadSignature(); + error OrderExpired(); + error WrongSeriesNonce(); + error SwapWithZeroAmount(); + error PartialFillNotAllowed(); + error OrderIsNotSuitableForMassInvalidation(); + error EpochManagerAndBitInvalidatorsAreIncompatible(); + error ReentrancyDetected(); + error PredicateIsNotTrue(); + error TakingAmountTooHigh(); + error MakingAmountTooLow(); + error TransferFromMakerToTakerFailed(); + error TransferFromTakerToMakerFailed(); + error MismatchArraysLengths(); + error InvalidPermit2Transfer(); + error SimulationResults(bool success, bytes res); + + /** + * @notice Emitted when order gets filled + * @param orderHash Hash of the order + * @param remainingAmount Amount of the maker asset that remains to be filled + */ + event OrderFilled( + bytes32 orderHash, + uint256 remainingAmount + ); + + /** + * @notice Emitted when order gets filled + * @param orderHash Hash of the order + */ + event OrderCancelled( + bytes32 orderHash + ); + + /** + * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes + * @param maker Maker address + * @param slot Slot number to return bitmask for + * @return result Each bit represents whether corresponding was already invalidated + */ + function bitInvalidatorForOrder(address maker, uint256 slot) external view returns(uint256 result); + + /** + * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes + * @param orderHash Hash of the order + * @return remaining Remaining amount of the order + */ + function remainingInvalidatorForOrder(address maker, bytes32 orderHash) external view returns(uint256 remaining); + + /** + * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes + * @param orderHash Hash of the order + * @return remainingRaw Remaining amount of the order plus 1 if order was partially filled, otherwise 0 + */ + function rawRemainingInvalidatorForOrder(address maker, bytes32 orderHash) external view returns(uint256 remainingRaw); + + /** + * @notice Cancels order's quote + * @param makerTraits Order makerTraits + * @param orderHash Hash of the order to cancel + */ + function cancelOrder(MakerTraits makerTraits, bytes32 orderHash) external; + + /** + * @notice Cancels orders' quotes + * @param makerTraits Orders makerTraits + * @param orderHashes Hashes of the orders to cancel + */ + function cancelOrders(MakerTraits[] calldata makerTraits, bytes32[] calldata orderHashes) external; + + /** + * @notice Cancels all quotes of the maker (works for bit-invalidating orders only) + * @param makerTraits Order makerTraits + * @param additionalMask Additional bitmask to invalidate orders + */ + function bitsInvalidateForOrder(MakerTraits makerTraits, uint256 additionalMask) external; + + /** + * @notice Returns order hash, hashed with limit order protocol contract EIP712 + * @param order Order + * @return orderHash Hash of the order + */ + function hashOrder(IOrderMixin.Order calldata order) external view returns(bytes32 orderHash); + + /** + * @notice Delegates execution to custom implementation. Could be used to validate if `transferFrom` works properly + * @dev The function always reverts and returns the simulation results in revert data. + * @param target Addresses that will be delegated + * @param data Data that will be passed to delegatee + */ + function simulate(address target, bytes calldata data) external; + + /** + * @notice Fills order's quote, fully or partially (whichever is possible). + * @param order Order quote to fill + * @param r R component of signature + * @param vs VS component of signature + * @param amount Taker amount to fill + * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies + * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. + * @return makingAmount Actual amount transferred from maker to taker + * @return takingAmount Actual amount transferred from taker to maker + * @return orderHash Hash of the filled order + */ + function fillOrder( + Order calldata order, + bytes32 r, + bytes32 vs, + uint256 amount, + TakerTraits takerTraits + ) external payable returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); + + /** + * @notice Same as `fillOrder` but allows to specify arguments that are used by the taker. + * @param order Order quote to fill + * @param r R component of signature + * @param vs VS component of signature + * @param amount Taker amount to fill + * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies + * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. + * @param args Arguments that are used by the taker (target, extension, interaction, permit) + * @return makingAmount Actual amount transferred from maker to taker + * @return takingAmount Actual amount transferred from taker to maker + * @return orderHash Hash of the filled order + */ + function fillOrderArgs( + IOrderMixin.Order calldata order, + bytes32 r, + bytes32 vs, + uint256 amount, + TakerTraits takerTraits, + bytes calldata args + ) external payable returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); + + /** + * @notice Same as `fillOrder` but uses contract-based signatures. + * @param order Order quote to fill + * @param signature Signature to confirm quote ownership + * @param amount Taker amount to fill + * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies + * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. + * @return makingAmount Actual amount transferred from maker to taker + * @return takingAmount Actual amount transferred from taker to maker + * @return orderHash Hash of the filled order + * @dev See tests for examples + */ + function fillContractOrder( + Order calldata order, + bytes calldata signature, + uint256 amount, + TakerTraits takerTraits + ) external returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); + + /** + * @notice Same as `fillContractOrder` but allows to specify arguments that are used by the taker. + * @param order Order quote to fill + * @param signature Signature to confirm quote ownership + * @param amount Taker amount to fill + * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies + * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. + * @param args Arguments that are used by the taker (target, extension, interaction, permit) + * @return makingAmount Actual amount transferred from maker to taker + * @return takingAmount Actual amount transferred from taker to maker + * @return orderHash Hash of the filled order + * @dev See tests for examples + */ + function fillContractOrderArgs( + Order calldata order, + bytes calldata signature, + uint256 amount, + TakerTraits takerTraits, + bytes calldata args + ) external returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); +} + +////import "./IOrderMixin.sol"; + +interface IAmountGetter { + /** + * @notice View method that gets called to determine the actual making amount + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param takingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function getMakingAmount( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external view returns (uint256); + + /** + * @notice View method that gets called to determine the actual making amount + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param makingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function getTakingAmount( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external view returns (uint256); +} + +////import "./IOrderMixin.sol"; + +interface IPreInteraction { + /** + * @notice Callback method that gets called before any funds transfers + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param makingAmount Actual making amount + * @param takingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function preInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external; +} + +////import "./IOrderMixin.sol"; + +interface IPostInteraction { + /** + * @notice Callback method that gets called after all fund transfers + * @param order Order being processed + * @param extension Order extension data + * @param orderHash Hash of the order being processed + * @param taker Taker address + * @param makingAmount Actual making amount + * @param takingAmount Actual taking amount + * @param remainingMakingAmount Order remaining making amount + * @param extraData Extra data + */ + function postInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external; +} + + +////import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +////import { IFeeBank } from "./interfaces/IFeeBank.sol"; +////import { IFeeBankCharger } from "./interfaces/IFeeBankCharger.sol"; +////import { FeeBank } from "./FeeBank.sol"; + +/** + * @title FeeBankCharger + * @notice FeeBankCharger contract implements logic to increase or decrease users' credits in FeeBank. + */ +contract FeeBankCharger is IFeeBankCharger { + error OnlyFeeBankAccess(); + error NotEnoughCredit(); + + /** + * @notice See {IFeeBankCharger-feeBank}. + */ + IFeeBank public immutable feeBank; + mapping(address => uint256) private _creditAllowance; + + /** + * @dev Modifier to check if the sender is a feeBank contract. + */ + modifier onlyFeeBank() { + if (msg.sender != address(feeBank)) revert OnlyFeeBankAccess(); + _; + } + + constructor(IERC20 token) { + feeBank = new FeeBank(this, token, msg.sender); + } + + /** + * @notice See {IFeeBankCharger-availableCredit}. + */ + function availableCredit(address account) external view returns (uint256) { + return _creditAllowance[account]; + } + + /** + * @notice See {IFeeBankCharger-increaseAvailableCredit}. + */ + function increaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) { + allowance = _creditAllowance[account]; + unchecked { + allowance += amount; // overflow is impossible due to limited _token supply + } + _creditAllowance[account] = allowance; + } + + /** + * @notice See {IFeeBankCharger-decreaseAvailableCredit}. + */ + function decreaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) { + return _creditAllowance[account] -= amount; // checked math is needed to prevent underflow + } + + /** + * @notice Internal function that charges a specified fee from a given account's credit allowance. + * @dev Reverts with 'NotEnoughCredit' if the account's credit allowance is insufficient to cover the fee. + * @param account The address of the account from which the fee is being charged. + * @param fee The amount of fee to be charged from the account. + */ + function _chargeFee(address account, uint256 fee) internal virtual { + if (fee > 0) { + uint256 currentAllowance = _creditAllowance[account]; + if (currentAllowance < fee) revert NotEnoughCredit(); + unchecked { + _creditAllowance[account] = currentAllowance - fee; + } + } + } +} + + +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; +////import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; +////import { IPostInteraction } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IPostInteraction.sol"; +////import { IPreInteraction } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IPreInteraction.sol"; +////import { IAmountGetter } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IAmountGetter.sol"; + +/** + * @title Base Extension contract + * @notice Contract to define the basic functionality for the limit orders settlement. + */ +contract BaseExtension is IPreInteraction, IPostInteraction, IAmountGetter { + error OnlyLimitOrderProtocol(); + + uint256 private constant _BASE_POINTS = 10_000_000; // 100% + + IOrderMixin private immutable _limitOrderProtocol; + + /// @dev Modifier to check if the caller is the limit order protocol contract. + modifier onlyLimitOrderProtocol { + if (msg.sender != address(_limitOrderProtocol)) revert OnlyLimitOrderProtocol(); + _; + } + + /** + * @notice Initializes the contract. + * @param limitOrderProtocol The limit order protocol contract. + */ + constructor(IOrderMixin limitOrderProtocol) { + _limitOrderProtocol = limitOrderProtocol; + } + + function getMakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 takingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + uint256 rateBump = _getRateBump(extraData); + return Math.mulDiv(order.makingAmount, takingAmount * _BASE_POINTS, order.takingAmount * (_BASE_POINTS + rateBump)); + } + + function getTakingAmount( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address /* taker */, + uint256 makingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) external view returns (uint256) { + uint256 rateBump = _getRateBump(extraData); + return Math.mulDiv(order.takingAmount, makingAmount * (_BASE_POINTS + rateBump), order.makingAmount * _BASE_POINTS); + } + + function preInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external onlyLimitOrderProtocol { + _preInteraction(order, extension, orderHash, taker, makingAmount, takingAmount, remainingMakingAmount, extraData); + } + + function postInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) external onlyLimitOrderProtocol { + _postInteraction(order, extension, orderHash, taker, makingAmount, takingAmount, remainingMakingAmount, extraData); + } + + /** + * @dev Parses rate bump data from the `auctionDetails` field. Auction is represented as a + * piecewise linear function with `N` points. Each point is represented as a pair of + * `(rateBump, timeDelta)`, where `rateBump` is the rate bump in basis points and `timeDelta` + * is the time delta in seconds. The rate bump is interpolated linearly between the points. + * The last point is assumed to be `(0, auctionDuration)`. + * @param auctionDetails AuctionDetails is a tihgtly packed struct of the following format: + * ``` + * struct AuctionDetails { + * bytes4 auctionStartTime; + * bytes3 auctionDuration; + * bytes3 initialRateBump; + * (bytes3,bytes2)[N] pointsAndTimeDeltas; + * } + * ``` + * @return rateBump The rate bump. + */ + function _getRateBump(bytes calldata auctionDetails) private view returns (uint256) { + unchecked { + uint256 auctionStartTime = uint32(bytes4(auctionDetails[0:4])); + uint256 auctionFinishTime = auctionStartTime + uint24(bytes3(auctionDetails[4:7])); + uint256 initialRateBump = uint24(bytes3(auctionDetails[7:10])); + + if (block.timestamp <= auctionStartTime) { + return initialRateBump; + } else if (block.timestamp >= auctionFinishTime) { + return 0; // Means 0% bump + } + + auctionDetails = auctionDetails[10:]; + uint256 pointsSize = auctionDetails.length / 5; + uint256 currentPointTime = auctionStartTime; + uint256 currentRateBump = initialRateBump; + + for (uint256 i = 0; i < pointsSize; i++) { + uint256 nextRateBump = uint24(bytes3(auctionDetails[:3])); + uint256 nextPointTime = currentPointTime + uint16(bytes2(auctionDetails[3:5])); + if (block.timestamp <= nextPointTime) { + return ((block.timestamp - currentPointTime) * nextRateBump + (nextPointTime - block.timestamp) * currentRateBump) / (nextPointTime - currentPointTime); + } + currentRateBump = nextRateBump; + currentPointTime = nextPointTime; + auctionDetails = auctionDetails[5:]; + } + return (auctionFinishTime - block.timestamp) * currentRateBump / (auctionFinishTime - currentPointTime); + } + } + + function _preInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) internal virtual {} + + function _postInteraction( + IOrderMixin.Order calldata order, + bytes calldata extension, + bytes32 orderHash, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 remainingMakingAmount, + bytes calldata extraData + ) internal virtual {} +} + +////import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +////import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; +////import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; +////import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; +////import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; +////import { BaseExtension } from "./BaseExtension.sol"; +////import { FeeBankCharger } from "./FeeBankCharger.sol"; + +/** + * @title Basic Settlement contract + * @notice Contract to execute limit orders settlement, created by Fusion mode. + */ +contract BasicSettlementExtension is BaseExtension, FeeBankCharger { + using SafeERC20 for IERC20; + using AddressLib for Address; + + error InvalidPriorityFee(); + error ResolverIsNotWhitelisted(); + + uint256 private constant _TAKING_FEE_BASE = 1e9; + uint256 private constant _ORDER_FEE_BASE_POINTS = 1e15; + + /** + * @notice Initializes the contract. + * @param limitOrderProtocol The limit order protocol contract. + * @param token The token to charge protocol fees in. + */ + constructor(IOrderMixin limitOrderProtocol, IERC20 token) + BaseExtension(limitOrderProtocol) + FeeBankCharger(token) {} + + /** + * @dev Parses fee data from the extraData field. + * @param extraData ExtraData is a tihgtly packed struct of the following format: + * ``` + * struct ExtraData { + * bytes1 feeTypes; 1 = resolverFee, 2 = integrationFee + * bytes4 resolverFee; optional + * bytes20 integrator; optional + * bytes4 integrationFee; optional + * bytes whitelist; + * } + * ``` + * @param orderMakingAmount The order making amount. + * @param actualMakingAmount The actual making amount. + * @param actualTakingAmount The actual taking amount. + * @return resolverFee The resolver fee. + * @return integrator The integrator address. + * @return integrationFee The integration fee. + * @return dataReturned The data remaining after parsing. + */ + function _parseFeeData( + bytes calldata extraData, + uint256 orderMakingAmount, + uint256 actualMakingAmount, + uint256 actualTakingAmount + ) internal pure virtual returns (uint256 resolverFee, address integrator, uint256 integrationFee, bytes calldata dataReturned) { + bytes1 feeType = extraData[0]; + extraData = extraData[1:]; + if (feeType & 0x01 == 0x01) { + // resolverFee enabled + resolverFee = uint256(uint32(bytes4(extraData[:4]))) * _ORDER_FEE_BASE_POINTS * actualMakingAmount / orderMakingAmount; + extraData = extraData[4:]; + } + if (feeType & 0x02 == 0x02) { + // integratorFee enabled + integrator = address(bytes20(extraData[:20])); + integrationFee = actualTakingAmount * uint256(uint32(bytes4(extraData[20:24]))) / _TAKING_FEE_BASE; + extraData = extraData[24:]; + } + dataReturned = extraData; + } + + /** + * @dev Validates whether the resolver is whitelisted. + * @param whitelist Whitelist is tighly packed struct of the following format: + * ``` + * struct WhitelistDetails { + * bytes4 auctionStartTime; + * (bytes10,bytes2)[N] resolversAddressesAndTimeDeltas; + * } + * ``` + * @param resolver The resolver to check. + * @return Whether the resolver is whitelisted. + */ + function _isWhitelisted(bytes calldata whitelist, address resolver) internal view virtual returns (bool) { + unchecked { + uint256 allowedTime = uint32(bytes4(whitelist[0:4])); // initially set to auction start time + whitelist = whitelist[4:]; + uint256 whitelistSize = whitelist.length / 12; + uint80 maskedResolverAddress = uint80(uint160(resolver)); + for (uint256 i = 0; i < whitelistSize; i++) { + uint80 whitelistedAddress = uint80(bytes10(whitelist[:10])); + allowedTime += uint16(bytes2(whitelist[10:12])); // add next time delta + if (maskedResolverAddress == whitelistedAddress) { + return allowedTime <= block.timestamp; + } else if (allowedTime > block.timestamp) { + return false; + } + whitelist = whitelist[12:]; + } + return false; + } + } + + function _isPriorityFeeValid() internal view virtual returns(bool) { + return true; + } + + function _postInteraction( + IOrderMixin.Order calldata order, + bytes calldata /* extension */, + bytes32 /* orderHash */, + address taker, + uint256 makingAmount, + uint256 takingAmount, + uint256 /* remainingMakingAmount */, + bytes calldata extraData + ) internal virtual override { + (uint256 resolverFee, address integrator, uint256 integrationFee, bytes calldata dataReturned) = _parseFeeData(extraData, order.makingAmount, makingAmount, takingAmount); + + if (!_isWhitelisted(dataReturned, taker)) revert ResolverIsNotWhitelisted(); + + if (!_isPriorityFeeValid()) revert InvalidPriorityFee(); + + _chargeFee(taker, resolverFee); + if (integrationFee > 0) { + IERC20(order.takerAsset.get()).safeTransferFrom(taker, integrator, integrationFee); + } + } +} + diff --git a/contracts/interfaces/IEscrowFactory.sol b/contracts/interfaces/IEscrowFactory.sol index 077d56a..a634ce4 100644 --- a/contracts/interfaces/IEscrowFactory.sol +++ b/contracts/interfaces/IEscrowFactory.sol @@ -55,5 +55,4 @@ interface IEscrowFactory { } error InsufficientEscrowBalance(); - error OnlyLimitOrderProtocol(); } diff --git a/test/EscrowFactory.js b/test/EscrowFactory.js index 44c28cd..caeaf13 100644 --- a/test/EscrowFactory.js +++ b/test/EscrowFactory.js @@ -26,7 +26,7 @@ describe('EscrowFactory', async function () { await escrowRegistry.waitForDeployment(); const EscrowFactory = await ethers.getContractFactory('EscrowFactory'); - const escrowFactory = await EscrowFactory.deploy(escrowRegistry, limitOrderProtocol); + const escrowFactory = await EscrowFactory.deploy(escrowRegistry, limitOrderProtocol, usdc.target); await escrowFactory.waitForDeployment(); const contracts = { escrowRegistry, escrowFactory, limitOrderProtocol }; diff --git a/test/helpers/escrowUtils.js b/test/helpers/escrowUtils.js index fd457bc..9ac8572 100644 --- a/test/helpers/escrowUtils.js +++ b/test/helpers/escrowUtils.js @@ -1,6 +1,8 @@ const hre = require('hardhat'); const { ethers } = hre; +const { trim0x } = require('@1inch/solidity-utils'); + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const srcTimelockDurations = { @@ -25,10 +27,10 @@ function buldDynamicData ({ safetyDeposit, }) { const hashlock = ethers.keccak256(getRandomBytes()); - const data = abiCoder.encode( + const data = '0x00' + trim0x(abiCoder.encode( ['uint256', 'uint256', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256'], [hashlock, chainId, token, safetyDeposit, ...Object.values(srcTimelockDurations), ...Object.values(dstTimelockDurations)], - ); + )); return { data, hashlock }; }; diff --git a/yarn.lock b/yarn.lock index 15fdd8c..833d3e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1392,9 +1392,9 @@ integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== "@types/node@*": - version "20.10.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198" - integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg== + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== dependencies: undici-types "~5.26.4" @@ -2924,9 +2924,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + version "1.16.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" + integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== dependencies: reusify "^1.0.4" @@ -5519,9 +5519,9 @@ ts-node@^10.9.1: yn "3.1.1" tsconfig-paths@^3.14.2: - version "3.14.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" - integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.2" From a44c822b91ed246c22ef64d0ca66e4db182ceb7d Mon Sep 17 00:00:00 2001 From: byshape Date: Tue, 19 Dec 2023 19:00:45 +0000 Subject: [PATCH 2/7] Updated the `BasicSettlementExtension` --- contracts/flatten/BasicSettlementExtension.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contracts/flatten/BasicSettlementExtension.sol b/contracts/flatten/BasicSettlementExtension.sol index b9bde5b..88405bd 100644 --- a/contracts/flatten/BasicSettlementExtension.sol +++ b/contracts/flatten/BasicSettlementExtension.sol @@ -1089,10 +1089,6 @@ contract BasicSettlementExtension is BaseExtension, FeeBankCharger { } } - function _isPriorityFeeValid() internal view virtual returns(bool) { - return true; - } - function _postInteraction( IOrderMixin.Order calldata order, bytes calldata /* extension */, @@ -1107,8 +1103,6 @@ contract BasicSettlementExtension is BaseExtension, FeeBankCharger { if (!_isWhitelisted(dataReturned, taker)) revert ResolverIsNotWhitelisted(); - if (!_isPriorityFeeValid()) revert InvalidPriorityFee(); - _chargeFee(taker, resolverFee); if (integrationFee > 0) { IERC20(order.takerAsset.get()).safeTransferFrom(taker, integrator, integrationFee); From ae9f6b0d30c24e38b496a86f1003d3f2418d2ee3 Mon Sep 17 00:00:00 2001 From: byshape Date: Fri, 22 Dec 2023 16:49:18 +0000 Subject: [PATCH 3/7] Bumped deps --- contracts/EscrowFactory.sol | 10 +- .../flatten/BasicSettlementExtension.sol | 1112 ----------------- hardhat.config.js | 2 +- package.json | 5 +- yarn.lock | 302 ++--- 5 files changed, 97 insertions(+), 1334 deletions(-) delete mode 100644 contracts/flatten/BasicSettlementExtension.sol diff --git a/contracts/EscrowFactory.sol b/contracts/EscrowFactory.sol index 4175534..6857910 100644 --- a/contracts/EscrowFactory.sol +++ b/contracts/EscrowFactory.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.23; // import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IOrderMixin, SimpleSettlementExtension } from "@1inch/limit-order-settlement/contracts/SimpleSettlementExtension.sol"; import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; import { ClonesWithImmutableArgs } from "clones-with-immutable-args/ClonesWithImmutableArgs.sol"; @@ -12,18 +13,15 @@ import { ClonesWithImmutableArgs } from "clones-with-immutable-args/ClonesWithIm import { IEscrowFactory } from "./interfaces/IEscrowFactory.sol"; import { EscrowRegistry } from "./EscrowRegistry.sol"; -// TODO: import from the package -import { BasicSettlementExtension, IOrderMixin } from "./flatten/BasicSettlementExtension.sol"; - -contract EscrowFactory is IEscrowFactory, BasicSettlementExtension { +contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { using AddressLib for Address; using ClonesWithImmutableArgs for address; using SafeERC20 for IERC20; address public immutable IMPLEMENTATION; - constructor(address implementation, IOrderMixin limitOrderProtocol, IERC20 token) - BasicSettlementExtension(limitOrderProtocol, token) + constructor(address implementation, address limitOrderProtocol, IERC20 token) + SimpleSettlementExtension(limitOrderProtocol, token) { IMPLEMENTATION = implementation; } diff --git a/contracts/flatten/BasicSettlementExtension.sol b/contracts/flatten/BasicSettlementExtension.sol deleted file mode 100644 index 88405bd..0000000 --- a/contracts/flatten/BasicSettlementExtension.sol +++ /dev/null @@ -1,1112 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.23; - -interface IFeeBank { - /** - * @notice Returns the available credit for a given account in the FeeBank contract. - * @param account The address of the account for which the available credit is being queried. - * @return availableCredit The available credit of the queried account. - */ - function availableCredit(address account) external view returns (uint256 availableCredit); - - /** - * @notice Increases the caller's available credit by the specified amount. - * @param amount The amount of credit to be added to the caller's account. - * @return totalAvailableCredit The updated available credit of the caller's account. - */ - function deposit(uint256 amount) external returns (uint256 totalAvailableCredit); - - /** - * @notice Increases the specified account's available credit by the specified amount. - * @param account The address of the account for which the available credit is being increased. - * @param amount The amount of credit to be added to the account. - * @return totalAvailableCredit The updated available credit of the specified account. - */ - function depositFor(address account, uint256 amount) external returns (uint256 totalAvailableCredit); - - /** - * @notice Increases the caller's available credit by a specified amount with permit. - * @param amount The amount of credit to be added to the caller's account. - * @param permit The permit data authorizing the transaction. - * @return totalAvailableCredit The updated available credit of the caller's account. - */ - function depositWithPermit(uint256 amount, bytes calldata permit) external returns (uint256 totalAvailableCredit); - - /** - * @notice Increases the specified account's available credit by a specified amount with permit. - * @param account The address of the account for which the available credit is being increased. - * @param amount The amount of credit to be added to the account. - * @param permit The permit data authorizing the transaction. - * @return totalAvailableCredit The updated available credit of the specified account. - */ - function depositForWithPermit(address account, uint256 amount, bytes calldata permit) external returns (uint256 totalAvailableCredit); - - /** - * @notice Withdraws a specified amount of credit from the caller's account. - * @param amount The amount of credit to be withdrawn from the caller's account. - * @return totalAvailableCredit The updated available credit of the caller's account. - */ - function withdraw(uint256 amount) external returns (uint256 totalAvailableCredit); - - /** - * @notice Withdraws a specified amount of credit to the specified account. - * @param account The address of the account to which the credit is being withdrawn. - * @param amount The amount of credit to be withdrawn. - * @return totalAvailableCredit The updated available credit of the caller's account. - */ - function withdrawTo(address account, uint256 amount) external returns (uint256 totalAvailableCredit); -} - -////import { IFeeBank } from "./IFeeBank.sol"; - -interface IFeeBankCharger { - /** - * @notice Returns the instance of the FeeBank contract. - * @return The instance of the FeeBank contract. - */ - function feeBank() external view returns (IFeeBank); - - /** - * @notice Returns the available credit for a given account. - * @param account The address of the account for which the available credit is being queried. - * @return The available credit of the queried account. - */ - function availableCredit(address account) external view returns (uint256); - - /** - * @notice Increases the available credit of a given account by a specified amount. - * @param account The address of the account for which the available credit is being increased. - * @param amount The amount by which the available credit will be increased. - * @return allowance The updated available credit of the specified account. - */ - function increaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance); - - /** - * @notice Decreases the available credit of a given account by a specified amount. - * @param account The address of the account for which the available credit is being decreased. - * @param amount The amount by which the available credit will be decreased. - * @return allowance The updated available credit of the specified account. - */ - function decreaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance); -} - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -////import { IFeeBankCharger } from "./interfaces/IFeeBankCharger.sol"; -////import { IFeeBank } from "./interfaces/IFeeBank.sol"; - -/** - * @title FeeBank - * @notice FeeBank contract introduces a credit system for paying fees. - * A user can deposit tokens to the FeeBank contract, obtain credits and then use them to pay fees. - * @dev FeeBank is coupled with FeeBankCharger to actually charge fees. - */ -contract FeeBank is IFeeBank, Ownable { - using SafeERC20 for IERC20; - - error ZeroAddress(); - - IERC20 private immutable _token; - IFeeBankCharger private immutable _charger; - - mapping(address account => uint256 availableCredit) private _accountDeposits; - - constructor(IFeeBankCharger charger_, IERC20 inch_, address owner_) Ownable(owner_) { - if (address(inch_) == address(0)) revert ZeroAddress(); - _charger = charger_; - _token = inch_; - } - - /** - * @notice See {IFeeBank-availableCredit}. - */ - function availableCredit(address account) external view returns (uint256) { - return _charger.availableCredit(account); - } - - /** - * @notice See {IFeeBank-deposit}. - */ - function deposit(uint256 amount) external returns (uint256) { - return _depositFor(msg.sender, amount); - } - - /** - * @notice See {IFeeBank-depositFor}. - */ - function depositFor(address account, uint256 amount) external returns (uint256) { - return _depositFor(account, amount); - } - - /** - * @notice See {IFeeBank-depositWithPermit}. - */ - function depositWithPermit(uint256 amount, bytes calldata permit) external returns (uint256) { - return depositForWithPermit(msg.sender, amount, permit); - } - - /** - * @notice See {IFeeBank-depositForWithPermit}. - */ - function depositForWithPermit( - address account, - uint256 amount, - bytes calldata permit - ) public returns (uint256) { - _token.safePermit(permit); - return _depositFor(account, amount); - } - - /** - * @notice See {IFeeBank-withdraw}. - */ - function withdraw(uint256 amount) external returns (uint256) { - return _withdrawTo(msg.sender, amount); - } - - /** - * @notice See {IFeeBank-withdrawTo}. - */ - function withdrawTo(address account, uint256 amount) external returns (uint256) { - return _withdrawTo(account, amount); - } - - /** - * @notice Admin method returns commissions spent by users. - * @param accounts Accounts whose commissions are being withdrawn. - * @return totalAccountFees The total amount of accounts commissions. - */ - function gatherFees(address[] calldata accounts) external onlyOwner returns (uint256 totalAccountFees) { - uint256 accountsLength = accounts.length; - unchecked { - for (uint256 i = 0; i < accountsLength; ++i) { - address account = accounts[i]; - uint256 accountDeposit = _accountDeposits[account]; - uint256 availableCredit_ = _charger.availableCredit(account); - _accountDeposits[account] = availableCredit_; - totalAccountFees += accountDeposit - availableCredit_; // overflow is impossible due to checks in FeeBankCharger - } - } - _token.safeTransfer(msg.sender, totalAccountFees); - } - - function _depositFor(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) { - if (account == address(0)) revert ZeroAddress(); - _token.safeTransferFrom(msg.sender, address(this), amount); - unchecked { - _accountDeposits[account] += amount; // overflow is impossible due to limited _token supply - } - totalAvailableCredit = _charger.increaseAvailableCredit(account, amount); - } - - function _withdrawTo(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) { - totalAvailableCredit = _charger.decreaseAvailableCredit(msg.sender, amount); - unchecked { - _accountDeposits[msg.sender] -= amount; // underflow is impossible due to checks in FeeBankCharger - } - _token.safeTransfer(account, amount); - } -} - -type TakerTraits is uint256; - -/** - * @title TakerTraitsLib - * @notice This library to manage and check TakerTraits, which are used to encode the taker's preferences for an order in a single uint256. - * @dev The TakerTraits are structured as follows: - * High bits are used for flags - * 255 bit `_MAKER_AMOUNT_FLAG` - If set, the taking amount is calculated based on making amount, otherwise making amount is calculated based on taking amount. - * 254 bit `_UNWRAP_WETH_FLAG` - If set, the WETH will be unwrapped into ETH before sending to taker. - * 253 bit `_SKIP_ORDER_PERMIT_FLAG` - If set, the order skips maker's permit execution. - * 252 bit `_USE_PERMIT2_FLAG` - If set, the order uses the permit2 function for authorization. - * The remaining bits are used to store the threshold amount (the maximum amount a taker agrees to give in exchange for a making amount). - */ -library TakerTraitsLib { - uint256 private constant _MAKER_AMOUNT_FLAG = 1 << 255; - uint256 private constant _UNWRAP_WETH_FLAG = 1 << 254; - uint256 private constant _SKIP_ORDER_PERMIT_FLAG = 1 << 253; - uint256 private constant _USE_PERMIT2_FLAG = 1 << 252; - uint256 private constant _ARGS_HAS_TARGET = 1 << 251; - - uint256 private constant _ARGS_EXTENSION_LENGTH_OFFSET = 224; - uint256 private constant _ARGS_EXTENSION_LENGTH_MASK = 0xffffff; - uint256 private constant _ARGS_INTERACTION_LENGTH_OFFSET = 200; - uint256 private constant _ARGS_INTERACTION_LENGTH_MASK = 0xffffff; - - uint256 private constant _AMOUNT_MASK = 0x000000000000000000ffffffffffffffffffffffffffffffffffffffffffffff; - - function argsHasTarget(TakerTraits takerTraits) internal pure returns (bool) { - return (TakerTraits.unwrap(takerTraits) & _ARGS_HAS_TARGET) != 0; - } - - function argsExtensionLength(TakerTraits takerTraits) internal pure returns (uint256) { - return (TakerTraits.unwrap(takerTraits) >> _ARGS_EXTENSION_LENGTH_OFFSET) & _ARGS_EXTENSION_LENGTH_MASK; - } - - function argsInteractionLength(TakerTraits takerTraits) internal pure returns (uint256) { - return (TakerTraits.unwrap(takerTraits) >> _ARGS_INTERACTION_LENGTH_OFFSET) & _ARGS_INTERACTION_LENGTH_MASK; - } - - /** - * @notice Checks if the taking amount should be calculated based on making amount. - * @param takerTraits The traits of the taker. - * @return result A boolean indicating whether the taking amount should be calculated based on making amount. - */ - function isMakingAmount(TakerTraits takerTraits) internal pure returns (bool) { - return (TakerTraits.unwrap(takerTraits) & _MAKER_AMOUNT_FLAG) != 0; - } - - /** - * @notice Checks if the order should unwrap WETH and send ETH to taker. - * @param takerTraits The traits of the taker. - * @return result A boolean indicating whether the order should unwrap WETH. - */ - function unwrapWeth(TakerTraits takerTraits) internal pure returns (bool) { - return (TakerTraits.unwrap(takerTraits) & _UNWRAP_WETH_FLAG) != 0; - } - - /** - * @notice Checks if the order should skip maker's permit execution. - * @param takerTraits The traits of the taker. - * @return result A boolean indicating whether the order don't apply permit. - */ - function skipMakerPermit(TakerTraits takerTraits) internal pure returns (bool) { - return (TakerTraits.unwrap(takerTraits) & _SKIP_ORDER_PERMIT_FLAG) != 0; - } - - /** - * @notice Checks if the order uses the permit2 instead of permit. - * @param takerTraits The traits of the taker. - * @return result A boolean indicating whether the order uses the permit2. - */ - function usePermit2(TakerTraits takerTraits) internal pure returns (bool) { - return (TakerTraits.unwrap(takerTraits) & _USE_PERMIT2_FLAG) != 0; - } - - /** - * @notice Retrieves the threshold amount from the takerTraits. - * The maximum amount a taker agrees to give in exchange for a making amount. - * @param takerTraits The traits of the taker. - * @return result The threshold amount encoded in the takerTraits. - */ - function threshold(TakerTraits takerTraits) internal pure returns (uint256) { - return TakerTraits.unwrap(takerTraits) & _AMOUNT_MASK; - } -} - -type MakerTraits is uint256; - -/** - * @title MakerTraitsLib - * @notice A library to manage and check MakerTraits, which are used to encode the maker's preferences for an order in a single uint256. - * @dev - * The MakerTraits type is a uint256 and different parts of the number are used to encode different traits. - * High bits are used for flags - * 255 bit `NO_PARTIAL_FILLS_FLAG` - if set, the order does not allow partial fills - * 254 bit `ALLOW_MULTIPLE_FILLS_FLAG` - if set, the order permits multiple fills - * 252 bit `PRE_INTERACTION_CALL_FLAG` - if set, the order requires pre-interaction call - * 251 bit `POST_INTERACTION_CALL_FLAG` - if set, the order requires post-interaction call - * 250 bit `NEED_CHECK_EPOCH_MANAGER_FLAG` - if set, the order requires to check the epoch manager - * 249 bit `HAS_EXTENSION_FLAG` - if set, the order has extension(s) - * 248 bit `USE_PERMIT2_FLAG` - if set, the order uses permit2 - * 247 bit `UNWRAP_WETH_FLAG` - if set, the order requires to unwrap WETH - - * Low 200 bits are used for allowed sender, expiration, nonceOrEpoch, and series - * uint80 last 10 bytes of allowed sender address (0 if any) - * uint40 expiration timestamp (0 if none) - * uint40 nonce or epoch - * uint40 series - */ -library MakerTraitsLib { - // Low 200 bits are used for allowed sender, expiration, nonceOrEpoch, and series - uint256 private constant _ALLOWED_SENDER_MASK = type(uint80).max; - uint256 private constant _EXPIRATION_OFFSET = 80; - uint256 private constant _EXPIRATION_MASK = type(uint40).max; - uint256 private constant _NONCE_OR_EPOCH_OFFSET = 120; - uint256 private constant _NONCE_OR_EPOCH_MASK = type(uint40).max; - uint256 private constant _SERIES_OFFSET = 160; - uint256 private constant _SERIES_MASK = type(uint40).max; - - uint256 private constant _NO_PARTIAL_FILLS_FLAG = 1 << 255; - uint256 private constant _ALLOW_MULTIPLE_FILLS_FLAG = 1 << 254; - uint256 private constant _PRE_INTERACTION_CALL_FLAG = 1 << 252; - uint256 private constant _POST_INTERACTION_CALL_FLAG = 1 << 251; - uint256 private constant _NEED_CHECK_EPOCH_MANAGER_FLAG = 1 << 250; - uint256 private constant _HAS_EXTENSION_FLAG = 1 << 249; - uint256 private constant _USE_PERMIT2_FLAG = 1 << 248; - uint256 private constant _UNWRAP_WETH_FLAG = 1 << 247; - - /** - * @notice Checks if the order has the extension flag set. - * @dev If the `HAS_EXTENSION_FLAG` is set in the makerTraits, then the protocol expects that the order has extension(s). - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the flag is set. - */ - function hasExtension(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _HAS_EXTENSION_FLAG) != 0; - } - - /** - * @notice Checks if the maker allows a specific taker to fill the order. - * @param makerTraits The traits of the maker. - * @param sender The address of the taker to be checked. - * @return result A boolean indicating whether the taker is allowed. - */ - function isAllowedSender(MakerTraits makerTraits, address sender) internal pure returns (bool) { - uint160 allowedSender = uint160(MakerTraits.unwrap(makerTraits) & _ALLOWED_SENDER_MASK); - return allowedSender == 0 || allowedSender == uint160(sender) & _ALLOWED_SENDER_MASK; - } - - /** - * @notice Checks if the order has expired. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the order has expired. - */ - function isExpired(MakerTraits makerTraits) internal view returns (bool) { - uint256 expiration = (MakerTraits.unwrap(makerTraits) >> _EXPIRATION_OFFSET) & _EXPIRATION_MASK; - return expiration != 0 && expiration < block.timestamp; // solhint-disable-line not-rely-on-time - } - - /** - * @notice Returns the nonce or epoch of the order. - * @param makerTraits The traits of the maker. - * @return result The nonce or epoch of the order. - */ - function nonceOrEpoch(MakerTraits makerTraits) internal pure returns (uint256) { - return (MakerTraits.unwrap(makerTraits) >> _NONCE_OR_EPOCH_OFFSET) & _NONCE_OR_EPOCH_MASK; - } - - /** - * @notice Returns the series of the order. - * @param makerTraits The traits of the maker. - * @return result The series of the order. - */ - function series(MakerTraits makerTraits) internal pure returns (uint256) { - return (MakerTraits.unwrap(makerTraits) >> _SERIES_OFFSET) & _SERIES_MASK; - } - - /** - * @notice Determines if the order allows partial fills. - * @dev If the _NO_PARTIAL_FILLS_FLAG is not set in the makerTraits, then the order allows partial fills. - * @param makerTraits The traits of the maker, determining their preferences for the order. - * @return result A boolean indicating whether the maker allows partial fills. - */ - function allowPartialFills(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _NO_PARTIAL_FILLS_FLAG) == 0; - } - - /** - * @notice Checks if the maker needs pre-interaction call. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the maker needs a pre-interaction call. - */ - function needPreInteractionCall(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _PRE_INTERACTION_CALL_FLAG) != 0; - } - - /** - * @notice Checks if the maker needs post-interaction call. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the maker needs a post-interaction call. - */ - function needPostInteractionCall(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _POST_INTERACTION_CALL_FLAG) != 0; - } - - /** - * @notice Determines if the order allows multiple fills. - * @dev If the _ALLOW_MULTIPLE_FILLS_FLAG is set in the makerTraits, then the maker allows multiple fills. - * @param makerTraits The traits of the maker, determining their preferences for the order. - * @return result A boolean indicating whether the maker allows multiple fills. - */ - function allowMultipleFills(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _ALLOW_MULTIPLE_FILLS_FLAG) != 0; - } - - /** - * @notice Determines if an order should use the bit invalidator or remaining amount validator. - * @dev The bit invalidator can be used if the order does not allow partial or multiple fills. - * @param makerTraits The traits of the maker, determining their preferences for the order. - * @return result A boolean indicating whether the bit invalidator should be used. - * True if the order requires the use of the bit invalidator. - */ - function useBitInvalidator(MakerTraits makerTraits) internal pure returns (bool) { - return !allowPartialFills(makerTraits) || !allowMultipleFills(makerTraits); - } - - /** - * @notice Checks if the maker needs to check the epoch. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the maker needs to check the epoch manager. - */ - function needCheckEpochManager(MakerTraits makerTraits) internal pure returns (bool) { - return (MakerTraits.unwrap(makerTraits) & _NEED_CHECK_EPOCH_MANAGER_FLAG) != 0; - } - - /** - * @notice Checks if the maker uses permit2. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the maker uses permit2. - */ - function usePermit2(MakerTraits makerTraits) internal pure returns (bool) { - return MakerTraits.unwrap(makerTraits) & _USE_PERMIT2_FLAG != 0; - } - - /** - * @notice Checks if the maker needs to unwraps WETH. - * @param makerTraits The traits of the maker. - * @return result A boolean indicating whether the maker needs to unwrap WETH. - */ - function unwrapWeth(MakerTraits makerTraits) internal pure returns (bool) { - return MakerTraits.unwrap(makerTraits) & _UNWRAP_WETH_FLAG != 0; - } -} - -import "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; -////import "../libraries/MakerTraitsLib.sol"; -////import "../libraries/TakerTraitsLib.sol"; - -interface IOrderMixin { - struct Order { - uint256 salt; - Address maker; - Address receiver; - Address makerAsset; - Address takerAsset; - uint256 makingAmount; - uint256 takingAmount; - MakerTraits makerTraits; - } - - error InvalidatedOrder(); - error TakingAmountExceeded(); - error PrivateOrder(); - error BadSignature(); - error OrderExpired(); - error WrongSeriesNonce(); - error SwapWithZeroAmount(); - error PartialFillNotAllowed(); - error OrderIsNotSuitableForMassInvalidation(); - error EpochManagerAndBitInvalidatorsAreIncompatible(); - error ReentrancyDetected(); - error PredicateIsNotTrue(); - error TakingAmountTooHigh(); - error MakingAmountTooLow(); - error TransferFromMakerToTakerFailed(); - error TransferFromTakerToMakerFailed(); - error MismatchArraysLengths(); - error InvalidPermit2Transfer(); - error SimulationResults(bool success, bytes res); - - /** - * @notice Emitted when order gets filled - * @param orderHash Hash of the order - * @param remainingAmount Amount of the maker asset that remains to be filled - */ - event OrderFilled( - bytes32 orderHash, - uint256 remainingAmount - ); - - /** - * @notice Emitted when order gets filled - * @param orderHash Hash of the order - */ - event OrderCancelled( - bytes32 orderHash - ); - - /** - * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes - * @param maker Maker address - * @param slot Slot number to return bitmask for - * @return result Each bit represents whether corresponding was already invalidated - */ - function bitInvalidatorForOrder(address maker, uint256 slot) external view returns(uint256 result); - - /** - * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes - * @param orderHash Hash of the order - * @return remaining Remaining amount of the order - */ - function remainingInvalidatorForOrder(address maker, bytes32 orderHash) external view returns(uint256 remaining); - - /** - * @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes - * @param orderHash Hash of the order - * @return remainingRaw Remaining amount of the order plus 1 if order was partially filled, otherwise 0 - */ - function rawRemainingInvalidatorForOrder(address maker, bytes32 orderHash) external view returns(uint256 remainingRaw); - - /** - * @notice Cancels order's quote - * @param makerTraits Order makerTraits - * @param orderHash Hash of the order to cancel - */ - function cancelOrder(MakerTraits makerTraits, bytes32 orderHash) external; - - /** - * @notice Cancels orders' quotes - * @param makerTraits Orders makerTraits - * @param orderHashes Hashes of the orders to cancel - */ - function cancelOrders(MakerTraits[] calldata makerTraits, bytes32[] calldata orderHashes) external; - - /** - * @notice Cancels all quotes of the maker (works for bit-invalidating orders only) - * @param makerTraits Order makerTraits - * @param additionalMask Additional bitmask to invalidate orders - */ - function bitsInvalidateForOrder(MakerTraits makerTraits, uint256 additionalMask) external; - - /** - * @notice Returns order hash, hashed with limit order protocol contract EIP712 - * @param order Order - * @return orderHash Hash of the order - */ - function hashOrder(IOrderMixin.Order calldata order) external view returns(bytes32 orderHash); - - /** - * @notice Delegates execution to custom implementation. Could be used to validate if `transferFrom` works properly - * @dev The function always reverts and returns the simulation results in revert data. - * @param target Addresses that will be delegated - * @param data Data that will be passed to delegatee - */ - function simulate(address target, bytes calldata data) external; - - /** - * @notice Fills order's quote, fully or partially (whichever is possible). - * @param order Order quote to fill - * @param r R component of signature - * @param vs VS component of signature - * @param amount Taker amount to fill - * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies - * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. - * @return makingAmount Actual amount transferred from maker to taker - * @return takingAmount Actual amount transferred from taker to maker - * @return orderHash Hash of the filled order - */ - function fillOrder( - Order calldata order, - bytes32 r, - bytes32 vs, - uint256 amount, - TakerTraits takerTraits - ) external payable returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); - - /** - * @notice Same as `fillOrder` but allows to specify arguments that are used by the taker. - * @param order Order quote to fill - * @param r R component of signature - * @param vs VS component of signature - * @param amount Taker amount to fill - * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies - * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. - * @param args Arguments that are used by the taker (target, extension, interaction, permit) - * @return makingAmount Actual amount transferred from maker to taker - * @return takingAmount Actual amount transferred from taker to maker - * @return orderHash Hash of the filled order - */ - function fillOrderArgs( - IOrderMixin.Order calldata order, - bytes32 r, - bytes32 vs, - uint256 amount, - TakerTraits takerTraits, - bytes calldata args - ) external payable returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); - - /** - * @notice Same as `fillOrder` but uses contract-based signatures. - * @param order Order quote to fill - * @param signature Signature to confirm quote ownership - * @param amount Taker amount to fill - * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies - * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. - * @return makingAmount Actual amount transferred from maker to taker - * @return takingAmount Actual amount transferred from taker to maker - * @return orderHash Hash of the filled order - * @dev See tests for examples - */ - function fillContractOrder( - Order calldata order, - bytes calldata signature, - uint256 amount, - TakerTraits takerTraits - ) external returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); - - /** - * @notice Same as `fillContractOrder` but allows to specify arguments that are used by the taker. - * @param order Order quote to fill - * @param signature Signature to confirm quote ownership - * @param amount Taker amount to fill - * @param takerTraits Specifies threshold as maximum allowed takingAmount when takingAmount is zero, otherwise specifies - * minimum allowed makingAmount. The 2nd (0 based index) highest bit specifies whether taker wants to skip maker's permit. - * @param args Arguments that are used by the taker (target, extension, interaction, permit) - * @return makingAmount Actual amount transferred from maker to taker - * @return takingAmount Actual amount transferred from taker to maker - * @return orderHash Hash of the filled order - * @dev See tests for examples - */ - function fillContractOrderArgs( - Order calldata order, - bytes calldata signature, - uint256 amount, - TakerTraits takerTraits, - bytes calldata args - ) external returns(uint256 makingAmount, uint256 takingAmount, bytes32 orderHash); -} - -////import "./IOrderMixin.sol"; - -interface IAmountGetter { - /** - * @notice View method that gets called to determine the actual making amount - * @param order Order being processed - * @param extension Order extension data - * @param orderHash Hash of the order being processed - * @param taker Taker address - * @param takingAmount Actual taking amount - * @param remainingMakingAmount Order remaining making amount - * @param extraData Extra data - */ - function getMakingAmount( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external view returns (uint256); - - /** - * @notice View method that gets called to determine the actual making amount - * @param order Order being processed - * @param extension Order extension data - * @param orderHash Hash of the order being processed - * @param taker Taker address - * @param makingAmount Actual taking amount - * @param remainingMakingAmount Order remaining making amount - * @param extraData Extra data - */ - function getTakingAmount( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external view returns (uint256); -} - -////import "./IOrderMixin.sol"; - -interface IPreInteraction { - /** - * @notice Callback method that gets called before any funds transfers - * @param order Order being processed - * @param extension Order extension data - * @param orderHash Hash of the order being processed - * @param taker Taker address - * @param makingAmount Actual making amount - * @param takingAmount Actual taking amount - * @param remainingMakingAmount Order remaining making amount - * @param extraData Extra data - */ - function preInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external; -} - -////import "./IOrderMixin.sol"; - -interface IPostInteraction { - /** - * @notice Callback method that gets called after all fund transfers - * @param order Order being processed - * @param extension Order extension data - * @param orderHash Hash of the order being processed - * @param taker Taker address - * @param makingAmount Actual making amount - * @param takingAmount Actual taking amount - * @param remainingMakingAmount Order remaining making amount - * @param extraData Extra data - */ - function postInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external; -} - - -////import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -////import { IFeeBank } from "./interfaces/IFeeBank.sol"; -////import { IFeeBankCharger } from "./interfaces/IFeeBankCharger.sol"; -////import { FeeBank } from "./FeeBank.sol"; - -/** - * @title FeeBankCharger - * @notice FeeBankCharger contract implements logic to increase or decrease users' credits in FeeBank. - */ -contract FeeBankCharger is IFeeBankCharger { - error OnlyFeeBankAccess(); - error NotEnoughCredit(); - - /** - * @notice See {IFeeBankCharger-feeBank}. - */ - IFeeBank public immutable feeBank; - mapping(address => uint256) private _creditAllowance; - - /** - * @dev Modifier to check if the sender is a feeBank contract. - */ - modifier onlyFeeBank() { - if (msg.sender != address(feeBank)) revert OnlyFeeBankAccess(); - _; - } - - constructor(IERC20 token) { - feeBank = new FeeBank(this, token, msg.sender); - } - - /** - * @notice See {IFeeBankCharger-availableCredit}. - */ - function availableCredit(address account) external view returns (uint256) { - return _creditAllowance[account]; - } - - /** - * @notice See {IFeeBankCharger-increaseAvailableCredit}. - */ - function increaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) { - allowance = _creditAllowance[account]; - unchecked { - allowance += amount; // overflow is impossible due to limited _token supply - } - _creditAllowance[account] = allowance; - } - - /** - * @notice See {IFeeBankCharger-decreaseAvailableCredit}. - */ - function decreaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) { - return _creditAllowance[account] -= amount; // checked math is needed to prevent underflow - } - - /** - * @notice Internal function that charges a specified fee from a given account's credit allowance. - * @dev Reverts with 'NotEnoughCredit' if the account's credit allowance is insufficient to cover the fee. - * @param account The address of the account from which the fee is being charged. - * @param fee The amount of fee to be charged from the account. - */ - function _chargeFee(address account, uint256 fee) internal virtual { - if (fee > 0) { - uint256 currentAllowance = _creditAllowance[account]; - if (currentAllowance < fee) revert NotEnoughCredit(); - unchecked { - _creditAllowance[account] = currentAllowance - fee; - } - } - } -} - - -import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; -////import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; -////import { IPostInteraction } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IPostInteraction.sol"; -////import { IPreInteraction } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IPreInteraction.sol"; -////import { IAmountGetter } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IAmountGetter.sol"; - -/** - * @title Base Extension contract - * @notice Contract to define the basic functionality for the limit orders settlement. - */ -contract BaseExtension is IPreInteraction, IPostInteraction, IAmountGetter { - error OnlyLimitOrderProtocol(); - - uint256 private constant _BASE_POINTS = 10_000_000; // 100% - - IOrderMixin private immutable _limitOrderProtocol; - - /// @dev Modifier to check if the caller is the limit order protocol contract. - modifier onlyLimitOrderProtocol { - if (msg.sender != address(_limitOrderProtocol)) revert OnlyLimitOrderProtocol(); - _; - } - - /** - * @notice Initializes the contract. - * @param limitOrderProtocol The limit order protocol contract. - */ - constructor(IOrderMixin limitOrderProtocol) { - _limitOrderProtocol = limitOrderProtocol; - } - - function getMakingAmount( - IOrderMixin.Order calldata order, - bytes calldata /* extension */, - bytes32 /* orderHash */, - address /* taker */, - uint256 takingAmount, - uint256 /* remainingMakingAmount */, - bytes calldata extraData - ) external view returns (uint256) { - uint256 rateBump = _getRateBump(extraData); - return Math.mulDiv(order.makingAmount, takingAmount * _BASE_POINTS, order.takingAmount * (_BASE_POINTS + rateBump)); - } - - function getTakingAmount( - IOrderMixin.Order calldata order, - bytes calldata /* extension */, - bytes32 /* orderHash */, - address /* taker */, - uint256 makingAmount, - uint256 /* remainingMakingAmount */, - bytes calldata extraData - ) external view returns (uint256) { - uint256 rateBump = _getRateBump(extraData); - return Math.mulDiv(order.takingAmount, makingAmount * (_BASE_POINTS + rateBump), order.makingAmount * _BASE_POINTS); - } - - function preInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external onlyLimitOrderProtocol { - _preInteraction(order, extension, orderHash, taker, makingAmount, takingAmount, remainingMakingAmount, extraData); - } - - function postInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) external onlyLimitOrderProtocol { - _postInteraction(order, extension, orderHash, taker, makingAmount, takingAmount, remainingMakingAmount, extraData); - } - - /** - * @dev Parses rate bump data from the `auctionDetails` field. Auction is represented as a - * piecewise linear function with `N` points. Each point is represented as a pair of - * `(rateBump, timeDelta)`, where `rateBump` is the rate bump in basis points and `timeDelta` - * is the time delta in seconds. The rate bump is interpolated linearly between the points. - * The last point is assumed to be `(0, auctionDuration)`. - * @param auctionDetails AuctionDetails is a tihgtly packed struct of the following format: - * ``` - * struct AuctionDetails { - * bytes4 auctionStartTime; - * bytes3 auctionDuration; - * bytes3 initialRateBump; - * (bytes3,bytes2)[N] pointsAndTimeDeltas; - * } - * ``` - * @return rateBump The rate bump. - */ - function _getRateBump(bytes calldata auctionDetails) private view returns (uint256) { - unchecked { - uint256 auctionStartTime = uint32(bytes4(auctionDetails[0:4])); - uint256 auctionFinishTime = auctionStartTime + uint24(bytes3(auctionDetails[4:7])); - uint256 initialRateBump = uint24(bytes3(auctionDetails[7:10])); - - if (block.timestamp <= auctionStartTime) { - return initialRateBump; - } else if (block.timestamp >= auctionFinishTime) { - return 0; // Means 0% bump - } - - auctionDetails = auctionDetails[10:]; - uint256 pointsSize = auctionDetails.length / 5; - uint256 currentPointTime = auctionStartTime; - uint256 currentRateBump = initialRateBump; - - for (uint256 i = 0; i < pointsSize; i++) { - uint256 nextRateBump = uint24(bytes3(auctionDetails[:3])); - uint256 nextPointTime = currentPointTime + uint16(bytes2(auctionDetails[3:5])); - if (block.timestamp <= nextPointTime) { - return ((block.timestamp - currentPointTime) * nextRateBump + (nextPointTime - block.timestamp) * currentRateBump) / (nextPointTime - currentPointTime); - } - currentRateBump = nextRateBump; - currentPointTime = nextPointTime; - auctionDetails = auctionDetails[5:]; - } - return (auctionFinishTime - block.timestamp) * currentRateBump / (auctionFinishTime - currentPointTime); - } - } - - function _preInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) internal virtual {} - - function _postInteraction( - IOrderMixin.Order calldata order, - bytes calldata extension, - bytes32 orderHash, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 remainingMakingAmount, - bytes calldata extraData - ) internal virtual {} -} - -////import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -////import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; -////import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; -////import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; -////import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; -////import { BaseExtension } from "./BaseExtension.sol"; -////import { FeeBankCharger } from "./FeeBankCharger.sol"; - -/** - * @title Basic Settlement contract - * @notice Contract to execute limit orders settlement, created by Fusion mode. - */ -contract BasicSettlementExtension is BaseExtension, FeeBankCharger { - using SafeERC20 for IERC20; - using AddressLib for Address; - - error InvalidPriorityFee(); - error ResolverIsNotWhitelisted(); - - uint256 private constant _TAKING_FEE_BASE = 1e9; - uint256 private constant _ORDER_FEE_BASE_POINTS = 1e15; - - /** - * @notice Initializes the contract. - * @param limitOrderProtocol The limit order protocol contract. - * @param token The token to charge protocol fees in. - */ - constructor(IOrderMixin limitOrderProtocol, IERC20 token) - BaseExtension(limitOrderProtocol) - FeeBankCharger(token) {} - - /** - * @dev Parses fee data from the extraData field. - * @param extraData ExtraData is a tihgtly packed struct of the following format: - * ``` - * struct ExtraData { - * bytes1 feeTypes; 1 = resolverFee, 2 = integrationFee - * bytes4 resolverFee; optional - * bytes20 integrator; optional - * bytes4 integrationFee; optional - * bytes whitelist; - * } - * ``` - * @param orderMakingAmount The order making amount. - * @param actualMakingAmount The actual making amount. - * @param actualTakingAmount The actual taking amount. - * @return resolverFee The resolver fee. - * @return integrator The integrator address. - * @return integrationFee The integration fee. - * @return dataReturned The data remaining after parsing. - */ - function _parseFeeData( - bytes calldata extraData, - uint256 orderMakingAmount, - uint256 actualMakingAmount, - uint256 actualTakingAmount - ) internal pure virtual returns (uint256 resolverFee, address integrator, uint256 integrationFee, bytes calldata dataReturned) { - bytes1 feeType = extraData[0]; - extraData = extraData[1:]; - if (feeType & 0x01 == 0x01) { - // resolverFee enabled - resolverFee = uint256(uint32(bytes4(extraData[:4]))) * _ORDER_FEE_BASE_POINTS * actualMakingAmount / orderMakingAmount; - extraData = extraData[4:]; - } - if (feeType & 0x02 == 0x02) { - // integratorFee enabled - integrator = address(bytes20(extraData[:20])); - integrationFee = actualTakingAmount * uint256(uint32(bytes4(extraData[20:24]))) / _TAKING_FEE_BASE; - extraData = extraData[24:]; - } - dataReturned = extraData; - } - - /** - * @dev Validates whether the resolver is whitelisted. - * @param whitelist Whitelist is tighly packed struct of the following format: - * ``` - * struct WhitelistDetails { - * bytes4 auctionStartTime; - * (bytes10,bytes2)[N] resolversAddressesAndTimeDeltas; - * } - * ``` - * @param resolver The resolver to check. - * @return Whether the resolver is whitelisted. - */ - function _isWhitelisted(bytes calldata whitelist, address resolver) internal view virtual returns (bool) { - unchecked { - uint256 allowedTime = uint32(bytes4(whitelist[0:4])); // initially set to auction start time - whitelist = whitelist[4:]; - uint256 whitelistSize = whitelist.length / 12; - uint80 maskedResolverAddress = uint80(uint160(resolver)); - for (uint256 i = 0; i < whitelistSize; i++) { - uint80 whitelistedAddress = uint80(bytes10(whitelist[:10])); - allowedTime += uint16(bytes2(whitelist[10:12])); // add next time delta - if (maskedResolverAddress == whitelistedAddress) { - return allowedTime <= block.timestamp; - } else if (allowedTime > block.timestamp) { - return false; - } - whitelist = whitelist[12:]; - } - return false; - } - } - - function _postInteraction( - IOrderMixin.Order calldata order, - bytes calldata /* extension */, - bytes32 /* orderHash */, - address taker, - uint256 makingAmount, - uint256 takingAmount, - uint256 /* remainingMakingAmount */, - bytes calldata extraData - ) internal virtual override { - (uint256 resolverFee, address integrator, uint256 integrationFee, bytes calldata dataReturned) = _parseFeeData(extraData, order.makingAmount, makingAmount, takingAmount); - - if (!_isWhitelisted(dataReturned, taker)) revert ResolverIsNotWhitelisted(); - - _chargeFee(taker, resolverFee); - if (integrationFee > 0) { - IERC20(order.takerAsset.get()).safeTransferFrom(taker, integrator, integrationFee); - } - } -} - diff --git a/hardhat.config.js b/hardhat.config.js index db74473..7674424 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -3,7 +3,7 @@ require('@nomicfoundation/hardhat-ethers'); require('@nomicfoundation/hardhat-verify'); require('dotenv').config(); require('hardhat-dependency-compiler'); -// require('hardhat-deploy'); +require('hardhat-deploy'); require('hardhat-gas-reporter'); // require('hardhat-tracer'); require('solidity-coverage'); diff --git a/package.json b/package.json index b277c34..89a7b87 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,10 @@ }, "license": "MIT", "dependencies": { - "@1inch/solidity-utils": "3.5.4", + "@1inch/solidity-utils": "3.5.5", "@openzeppelin/contracts": "5.0.1", - "@1inch/limit-order-protocol-contract": "4.0.0-prerelease-15" + "@1inch/limit-order-protocol-contract": "4.0.0-prerelease-16", + "@1inch/limit-order-settlement": "2.0.0-prerelease-3" }, "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "2.0.2", diff --git a/yarn.lock b/yarn.lock index 833d3e3..38650fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,45 +2,80 @@ # yarn lockfile v1 -"@1inch/limit-order-protocol-contract@4.0.0-prerelease-15": - version "4.0.0-prerelease-15" - resolved "https://registry.yarnpkg.com/@1inch/limit-order-protocol-contract/-/limit-order-protocol-contract-4.0.0-prerelease-15.tgz#574b1ca2b19b47d8d6d071e80ecc0f9010d273d0" - integrity sha512-lKV5biQWgVDdSEwTitfXbuEZuBou1E7tN6NikS1Y+dPmPTESGkd5YLEycGJILw6VXx/f5fbLo65rbX6tlolxQw== +"@1inch/delegating@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@1inch/delegating/-/delegating-1.1.0.tgz#d7a14c5033ffa297e92d78c96b71aecc5162795f" + integrity sha512-7FGsu7xRYy/hEhOmlj60rJ4yrhtEWPX6ikqq7dbadWZpdqg+Mfe3rHOUZ2sV/YgRLZu4N+VDNzKhv0mws/oo8g== + dependencies: + "@1inch/farming" "3.2.0" + "@1inch/solidity-utils" "3.5.5" + "@1inch/token-plugins" "1.3.0" + "@openzeppelin/contracts" "5.0.1" + +"@1inch/farming@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@1inch/farming/-/farming-3.2.0.tgz#0091a713f7df3c99050e7a98b5d168ddc83fb3de" + integrity sha512-5XM2hH5fC5pkCYW6diCl2/TuaitPHQbkqfIOFgXyBUFqKey9+ZaKG/qtKTtS8r2S2SACjUiM54lczVMw4meZfg== + dependencies: + "@1inch/solidity-utils" "3.5.5" + "@1inch/token-plugins" "1.3.0" + "@openzeppelin/contracts" "5.0.1" + +"@1inch/limit-order-protocol-contract@4.0.0-prerelease-16": + version "4.0.0-prerelease-16" + resolved "https://registry.yarnpkg.com/@1inch/limit-order-protocol-contract/-/limit-order-protocol-contract-4.0.0-prerelease-16.tgz#95863fc36e83901d4b83c897390c6440b93317d1" + integrity sha512-d3AHzXIjMyfGUwZwpqoBSGYEmqO/mm14FCAAEgK4gumCdrPkacdXOosujs9eutEr3zyBPh5Q3BxeWi3wwkDgMA== dependencies: - "@1inch/solidity-utils" "2.2.27" + "@1inch/solidity-utils" "3.5.5" "@chainlink/contracts" "0.6.1" - "@openzeppelin/contracts" "4.9.0" - -"@1inch/solidity-utils@2.2.27": - version "2.2.27" - resolved "https://registry.yarnpkg.com/@1inch/solidity-utils/-/solidity-utils-2.2.27.tgz#28a131304788674042dae002e817b2cd9346f232" - integrity sha512-rybgnA5Bd1+XRrAdIK3sNWWIMXZ5tWl4Ds4IwZVCzAXMLvxdXnJyb6zm//uuko9cRH63aDjct5Mzf+ggg36AJg== - dependencies: - "@metamask/eth-sig-util" "5.0.2" - "@nomicfoundation/hardhat-network-helpers" "1.0.8" - "@nomiclabs/hardhat-ethers" "2.2.2" - "@openzeppelin/contracts" "4.8.2" - "@uniswap/permit2-sdk" "^1.2.0" - ethereumjs-util "7.1.5" - ethers "5.7.2" + "@openzeppelin/contracts" "5.0.1" + +"@1inch/limit-order-settlement@2.0.0-prerelease-3": + version "2.0.0-prerelease-3" + resolved "https://registry.yarnpkg.com/@1inch/limit-order-settlement/-/limit-order-settlement-2.0.0-prerelease-3.tgz#0767f1333db4b4c4fae4406f6c9edbeb6d92310a" + integrity sha512-U8v+pbR2stCvAHQU8TnSP/L9cKQ71EP4PvswjbMXawoNYUIBr7c/RzqC6wzfIlRC3v2M9FyperbAx82wmtNyjg== + dependencies: + "@1inch/delegating" "1.1.0" + "@1inch/limit-order-protocol-contract" "4.0.0-prerelease-16" + "@1inch/solidity-utils" "3.5.5" + "@1inch/st1inch" "2.2.0" + "@openzeppelin/contracts" "5.0.1" -"@1inch/solidity-utils@3.5.4": - version "3.5.4" - resolved "https://registry.yarnpkg.com/@1inch/solidity-utils/-/solidity-utils-3.5.4.tgz#427147f300eb8cbdee2e3512dca96e2e15101ca7" - integrity sha512-uX4vhCMBw/2z+fNCfZQ0H2RPMva0wp62voZ2mwTktIPLLp0d5xslvmoJPbuLq6vDn1EWo3trw3u/qeGDn1n0KQ== +"@1inch/solidity-utils@3.5.5": + version "3.5.5" + resolved "https://registry.yarnpkg.com/@1inch/solidity-utils/-/solidity-utils-3.5.5.tgz#14353aa36270e4213927c7de31088953aa277a25" + integrity sha512-uX9fzLLxQIvXB4gIczTZ11C2tRrqswJsXV7WNhdPn5CZnCrp8gyBGnuxLjEbY1jZK+NPs2AtZB7FD+/+0ZN+Kg== dependencies: - "@metamask/eth-sig-util" "7.0.0" + "@metamask/eth-sig-util" "7.0.1" "@nomicfoundation/hardhat-ethers" "3.0.5" - "@nomicfoundation/hardhat-network-helpers" "1.0.9" - "@nomicfoundation/hardhat-verify" "2.0.1" - "@openzeppelin/contracts" "5.0.0" + "@nomicfoundation/hardhat-network-helpers" "1.0.10" + "@nomicfoundation/hardhat-verify" "2.0.2" + "@openzeppelin/contracts" "5.0.1" "@uniswap/permit2-sdk" "1.2.0" chai "4.3.10" dotenv "16.3.1" ethereumjs-util "7.1.5" - ethers "6.8.1" - hardhat "2.19.1" - hardhat-deploy "0.11.43" + ethers "6.9.0" + hardhat "2.19.2" + hardhat-deploy "0.11.44" + +"@1inch/st1inch@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@1inch/st1inch/-/st1inch-2.2.0.tgz#3dc39ee49d6954613dc951233afdd0c766864507" + integrity sha512-bsle68chQS/d2K1//1S6u9g/Yq3so1qtuQEXIJw9vs74lZbdpLUcgMTQ9MTmGaCfs4cn2Da2MmTKSLX/yXMnog== + dependencies: + "@1inch/farming" "3.2.0" + "@1inch/solidity-utils" "3.5.5" + "@1inch/token-plugins" "1.3.0" + "@openzeppelin/contracts" "5.0.1" + +"@1inch/token-plugins@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@1inch/token-plugins/-/token-plugins-1.3.0.tgz#365d50d4953225816a4749301150c6612b13e874" + integrity sha512-Um/8GKAC2Q2C6sITmGj+zr1xiJ3/jPtR/FllwMsDrdfEr7+AVbKH+GL755A7/MS8qz2Df10gSS8iz9Dj/N7/0g== + dependencies: + "@1inch/solidity-utils" "3.5.5" + "@openzeppelin/contracts" "5.0.1" "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" @@ -213,7 +248,7 @@ "@ethereumjs/util" "^8.1.0" ethereum-cryptography "^2.0.0" -"@ethereumjs/util@^8.0.0", "@ethereumjs/util@^8.1.0": +"@ethereumjs/util@^8.1.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== @@ -626,28 +661,15 @@ "@metamask/utils" "^8.0.0" superstruct "^1.0.3" -"@metamask/eth-sig-util@5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-5.0.2.tgz#c518279a6e17a88135a13d53a0b970f145ff8bce" - integrity sha512-RU6fG/H6/UlBol221uBkq5C7w3TwLK611nEZliO2u+kO0vHKGBXnIPlhI0tzKUigjhUeOd9mhCNbNvhh0LKt9Q== - dependencies: - "@ethereumjs/util" "^8.0.0" - bn.js "^4.11.8" - ethereum-cryptography "^1.1.2" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - -"@metamask/eth-sig-util@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-7.0.0.tgz#b035a2b826018578a5d463668bb64828271376d8" - integrity sha512-8KeXZB4SKx3EfNS5ahbjUMegyGvDQYk6Nk3hmM658sXpfAQR5ZlIXBgj+9RF+ZROqsU6EuNVgKt7Fr10re60PQ== +"@metamask/eth-sig-util@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-7.0.1.tgz#ad3227d6120f15f9293478de7dd9685a5c329586" + integrity sha512-59GSrMyFH2fPfu7nKeIQdZ150zxXNNhAQIUaFRUW+MGtVA4w/ONbiQobcRBLi+jQProfIyss51G8pfLPcQ0ylg== dependencies: "@ethereumjs/util" "^8.1.0" "@metamask/abi-utils" "^2.0.2" "@metamask/utils" "^8.1.0" ethereum-cryptography "^2.1.2" - ethjs-util "^0.1.6" tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" @@ -895,35 +917,6 @@ dependencies: ethereumjs-util "^7.1.4" -"@nomicfoundation/hardhat-network-helpers@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz#e4fe1be93e8a65508c46d73c41fa26c7e9f84931" - integrity sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q== - dependencies: - ethereumjs-util "^7.1.4" - -"@nomicfoundation/hardhat-network-helpers@1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz#767449e8a2acda79306ac84626117583d95d25aa" - integrity sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q== - dependencies: - ethereumjs-util "^7.1.4" - -"@nomicfoundation/hardhat-verify@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.1.tgz#1b9d707516f8e5db4e1d6bd679acbfd71e567928" - integrity sha512-TuJrhW5p9x92wDRiRhNkGQ/wzRmOkfCLkoRg8+IRxyeLigOALbayQEmkNiGWR03vGlxZS4znXhKI7y97JwZ6Og== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^8.1.0" - chalk "^2.4.2" - debug "^4.1.1" - lodash.clonedeep "^4.5.0" - semver "^6.3.0" - table "^6.8.0" - undici "^5.14.0" - "@nomicfoundation/hardhat-verify@2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.2.tgz#085f8509a335db44ea3bf39a8561f1ce0462fea2" @@ -1005,11 +998,6 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" -"@nomiclabs/hardhat-ethers@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.2.tgz#812d48929c3bf8fe840ec29eab4b613693467679" - integrity sha512-NLDlDFL2us07C0jB/9wzvR0kuLivChJWCXTKcj3yqjZqMoYp7g7wwS157F70VHx/+9gHIBGzak5pKDwG8gEefA== - "@oclif/command@^1.8.0": version "1.8.36" resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.36.tgz#9739b9c268580d064a50887c4597d1b4e86ca8b5" @@ -1138,21 +1126,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2.tgz#d81f786fda2871d1eb8a8c5a73e455753ba53527" integrity sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA== -"@openzeppelin/contracts@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.2.tgz#d815ade0027b50beb9bcca67143c6bcc3e3923d6" - integrity sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g== - -"@openzeppelin/contracts@4.9.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.0.tgz#683f33b6598970051bc5f0806fd8660da9e018dd" - integrity sha512-DUP74AFGKlic2sQb/CmgrN2aUPMFGxRrmCTUxLHsiU2RzwWqVuMPZBxiAyvlff6Pea77uylAX6B5x9W6evEbhA== - -"@openzeppelin/contracts@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c" - integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw== - "@openzeppelin/contracts@5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.1.tgz#93da90fc209a0a4ff09c1deb037fbb35e4020890" @@ -1421,9 +1394,9 @@ "@types/node" "*" "@types/qs@^6.2.31", "@types/qs@^6.9.7": - version "6.9.10" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" - integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw== + version "6.9.11" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" + integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== "@types/readable-stream@^2.3.13": version "2.3.15" @@ -1445,7 +1418,7 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@uniswap/permit2-sdk@1.2.0", "@uniswap/permit2-sdk@^1.2.0": +"@uniswap/permit2-sdk@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@uniswap/permit2-sdk/-/permit2-sdk-1.2.0.tgz#ed86440a87a6c318169c8e6f161fc263ad040891" integrity sha512-Ietv3FxN7+RCXcPSED/i/8b0a2GUZrMdyX05k3FsSztvYKyPFAMS/hBXojF0NZqYB1bHecqYc7Ej+7tV/rdYXg== @@ -2754,7 +2727,7 @@ ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereum-cryptography@^1.0.3, ethereum-cryptography@^1.1.2: +ethereum-cryptography@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== @@ -2806,7 +2779,20 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethers@5.7.2, ethers@^5.3.1, ethers@^5.6.1, ethers@^5.7.0, ethers@^5.7.1, ethers@^5.7.2: +ethers@6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.9.0.tgz#a4534bdcdfde306aee94ef32f3d5c70d7e33fcb9" + integrity sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +ethers@^5.3.1, ethers@^5.6.1, ethers@^5.7.0, ethers@^5.7.1, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -2842,32 +2828,6 @@ ethers@5.7.2, ethers@^5.3.1, ethers@^5.6.1, ethers@^5.7.0, ethers@^5.7.1, ethers "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethers@6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.8.1.tgz#ee2a1a39b5f62a13678f90ccd879175391d0a2b4" - integrity sha512-iEKm6zox5h1lDn6scuRWdIdFJUCGg3+/aQWu0F4K0GVyEZiktFkqrJbRjTn1FlYEPz7RKA707D6g5Kdk6j7Ljg== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - -ethers@6.9.0: - version "6.9.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.9.0.tgz#a4534bdcdfde306aee94ef32f3d5c70d7e33fcb9" - integrity sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -3332,36 +3292,6 @@ hardhat-dependency-compiler@1.1.3: resolved "https://registry.yarnpkg.com/hardhat-dependency-compiler/-/hardhat-dependency-compiler-1.1.3.tgz#1e49e23f68878bd713f860c66648a711bc4a4a79" integrity sha512-bCDqsOxGST6WkbMvj4lPchYWidNSSBm5CFnkyAex1T11cGmr9otZTGl81W6f9pmrtBXbKCvr3OSuNJ6Q394sAw== -hardhat-deploy@0.11.43: - version "0.11.43" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.43.tgz#b22ff15b3ea201b72ba0f17f4b2e182cc950e73e" - integrity sha512-D760CjDtinwjOCpKOvdyRtIJYLQIYXmhfgkFe+AkxlYM9bPZ/T4tZ/xIB2tR89ZT+z0hF1YuZFBXIL3/G/9T5g== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@ethersproject/providers" "^5.7.2" - "@ethersproject/solidity" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wallet" "^5.7.0" - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.7.0" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.14.3" - hardhat-deploy@0.11.44: version "0.11.44" resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.44.tgz#a7a771a675a3837ce4c321f2c18d4b6fa1ed03a0" @@ -3410,60 +3340,6 @@ hardhat-tracer@2.7.0: debug "^4.3.4" ethers "^5.6.1" -hardhat@2.19.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.1.tgz#5e09e8070ecfc6109ba9d3a4a117ec2b0643032a" - integrity sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.2" - "@nomicfoundation/ethereumjs-blockchain" "7.0.2" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-evm" "2.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-statemanager" "2.0.2" - "@nomicfoundation/ethereumjs-trie" "6.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - "@nomicfoundation/ethereumjs-vm" "7.0.2" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - hardhat@2.19.2: version "2.19.2" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.2.tgz#815819e4efd234941d495decb718b358d572e2c8" From 0b062835ae8376fba77b71d698eac3eec35315df Mon Sep 17 00:00:00 2001 From: byshape Date: Fri, 22 Dec 2023 16:50:59 +0000 Subject: [PATCH 4/7] Fixed lint --- test/helpers/escrowUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/escrowUtils.js b/test/helpers/escrowUtils.js index 9ac8572..2903260 100644 --- a/test/helpers/escrowUtils.js +++ b/test/helpers/escrowUtils.js @@ -27,7 +27,7 @@ function buldDynamicData ({ safetyDeposit, }) { const hashlock = ethers.keccak256(getRandomBytes()); - const data = '0x00' + trim0x(abiCoder.encode( + const data = '0x00' + trim0x(abiCoder.encode( ['uint256', 'uint256', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256'], [hashlock, chainId, token, safetyDeposit, ...Object.values(srcTimelockDurations), ...Object.values(dstTimelockDurations)], )); From 7c9e4af3af3390f42b3300cb7d9ad5beeb80c188 Mon Sep 17 00:00:00 2001 From: byshape Date: Fri, 22 Dec 2023 16:54:19 +0000 Subject: [PATCH 5/7] Removed unused import --- contracts/EscrowFactory.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/EscrowFactory.sol b/contracts/EscrowFactory.sol index 6857910..4d62c78 100644 --- a/contracts/EscrowFactory.sol +++ b/contracts/EscrowFactory.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.23; -// import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IOrderMixin, SimpleSettlementExtension } from "@1inch/limit-order-settlement/contracts/SimpleSettlementExtension.sol"; From 9903c31ad7a4bdc07be5489bb6494be2025b81bd Mon Sep 17 00:00:00 2001 From: byshape Date: Tue, 2 Jan 2024 11:00:29 +0000 Subject: [PATCH 6/7] Fixed merge bugs --- contracts/EscrowFactory.sol | 8 ++++---- contracts/interfaces/IEscrowFactory.sol | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/contracts/EscrowFactory.sol b/contracts/EscrowFactory.sol index 59e9514..f314702 100644 --- a/contracts/EscrowFactory.sol +++ b/contracts/EscrowFactory.sol @@ -46,8 +46,8 @@ contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { bytes calldata dataReturned ) = _parseFeeData(extraData, order.makingAmount, makingAmount, takingAmount); - bytes calldata extraDataParams = dataReturned[:320]; - bytes calldata whitelist = dataReturned[320:]; + bytes calldata extraDataParams = dataReturned[:288]; + bytes calldata whitelist = dataReturned[288:]; if (!_isWhitelisted(whitelist, taker)) revert ResolverIsNotWhitelisted(); @@ -113,8 +113,8 @@ contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { function _createEscrow( bytes memory data, bytes32 salt - ) private returns (EscrowRegistry clone) { - clone = EscrowRegistry(IMPLEMENTATION.clone3(data, salt)); + ) private returns (Escrow clone) { + clone = Escrow(IMPLEMENTATION.clone3(data, salt)); } function _isWhitelisted(bytes calldata /* whitelist */, address /* resolver */) internal view override returns (bool) { diff --git a/contracts/interfaces/IEscrowFactory.sol b/contracts/interfaces/IEscrowFactory.sol index 96f1a42..84d00fe 100644 --- a/contracts/interfaces/IEscrowFactory.sol +++ b/contracts/interfaces/IEscrowFactory.sol @@ -18,5 +18,4 @@ interface IEscrowFactory { error InsufficientEscrowBalance(); error InvalidCreationTime(); - error OnlyLimitOrderProtocol(); } From 8a33aebfeeaa0b39726cbb9b3e548e6c69d0c402 Mon Sep 17 00:00:00 2001 From: Mikhail Melnik Date: Mon, 8 Jan 2024 18:22:02 +0400 Subject: [PATCH 7/7] inherit EscrowFactory from ExtensionBase --- contracts/EscrowFactory.sol | 31 ++++--------------------------- test/EscrowFactory.js | 2 +- test/helpers/escrowUtils.js | 4 ++-- 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/contracts/EscrowFactory.sol b/contracts/EscrowFactory.sol index f314702..b2e054a 100644 --- a/contracts/EscrowFactory.sol +++ b/contracts/EscrowFactory.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.23; import { IOrderMixin } from "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { IOrderMixin, SimpleSettlementExtension } from "@1inch/limit-order-settlement/contracts/SimpleSettlementExtension.sol"; +import { ExtensionBase } from "@1inch/limit-order-settlement/contracts/ExtensionBase.sol"; import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol"; import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; import { ClonesWithImmutableArgs } from "clones-with-immutable-args/ClonesWithImmutableArgs.sol"; @@ -13,16 +13,14 @@ import { ClonesWithImmutableArgs } from "clones-with-immutable-args/ClonesWithIm import { IEscrowFactory } from "./interfaces/IEscrowFactory.sol"; import { Escrow } from "./Escrow.sol"; -contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { +contract EscrowFactory is IEscrowFactory, ExtensionBase { using AddressLib for Address; using ClonesWithImmutableArgs for address; using SafeERC20 for IERC20; address public immutable IMPLEMENTATION; - constructor(address implementation, address limitOrderProtocol, IERC20 token) - SimpleSettlementExtension(limitOrderProtocol, token) - { + constructor(address implementation, address limitOrderProtocol) ExtensionBase(limitOrderProtocol) { IMPLEMENTATION = implementation; } @@ -39,23 +37,6 @@ contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { uint256 /* remainingMakingAmount */, bytes calldata extraData ) internal override { - ( - uint256 resolverFee, - address integrator, - uint256 integrationFee, - bytes calldata dataReturned - ) = _parseFeeData(extraData, order.makingAmount, makingAmount, takingAmount); - - bytes calldata extraDataParams = dataReturned[:288]; - bytes calldata whitelist = dataReturned[288:]; - - if (!_isWhitelisted(whitelist, taker)) revert ResolverIsNotWhitelisted(); - - _chargeFee(taker, resolverFee); - if (integrationFee > 0) { - IERC20(order.takerAsset.get()).safeTransferFrom(taker, integrator, integrationFee); - } - bytes memory interactionParams = abi.encode( order.maker, taker, @@ -67,7 +48,7 @@ contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { bytes memory data = abi.encodePacked( block.timestamp, // deployedAt interactionParams, - extraDataParams + extraData ); // Salt is orderHash address escrow = ClonesWithImmutableArgs.addressOfClone3(orderHash); @@ -116,8 +97,4 @@ contract EscrowFactory is IEscrowFactory, SimpleSettlementExtension { ) private returns (Escrow clone) { clone = Escrow(IMPLEMENTATION.clone3(data, salt)); } - - function _isWhitelisted(bytes calldata /* whitelist */, address /* resolver */) internal view override returns (bool) { - return true; - } } diff --git a/test/EscrowFactory.js b/test/EscrowFactory.js index f9351eb..159d8fa 100644 --- a/test/EscrowFactory.js +++ b/test/EscrowFactory.js @@ -32,7 +32,7 @@ describe('EscrowFactory', async function () { await escrowRegistry.waitForDeployment(); const EscrowFactory = await ethers.getContractFactory('EscrowFactory'); - const escrowFactory = await EscrowFactory.deploy(escrowRegistry, limitOrderProtocol, usdc.target); + const escrowFactory = await EscrowFactory.deploy(escrowRegistry, limitOrderProtocol); await escrowFactory.waitForDeployment(); const contracts = { escrowRegistry, escrowFactory, limitOrderProtocol }; diff --git a/test/helpers/escrowUtils.js b/test/helpers/escrowUtils.js index f4cfafe..c33db84 100644 --- a/test/helpers/escrowUtils.js +++ b/test/helpers/escrowUtils.js @@ -30,10 +30,10 @@ function buldDynamicData ({ }) { const secret = buildSecret(); const hashlock = ethers.keccak256(secret); - const data = '0x00' + trim0x(abiCoder.encode( + const data = abiCoder.encode( ['uint256', 'uint256', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256'], [hashlock, chainId, token, safetyDeposit, ...Object.values(srcTimelockDurations), ...Object.values(dstTimelockDurations)], - )); + ); return { data, hashlock, secret }; };