Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
OrderRegistrator
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import { Address, AddressLib } from "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";
import { ECDSA } from "@1inch/solidity-utils/contracts/libraries/ECDSA.sol";
import { IOrderMixin } from "../interfaces/IOrderMixin.sol";
import { IOrderRegistrator } from "../interfaces/IOrderRegistrator.sol";
import { OrderLib } from "../OrderLib.sol";
/**
* @title OrderRegistrator
*/
contract OrderRegistrator is IOrderRegistrator {
using AddressLib for Address;
using OrderLib for IOrderMixin.Order;
IOrderMixin private immutable _LIMIT_ORDER_PROTOCOL;
constructor(IOrderMixin limitOrderProtocol) {
_LIMIT_ORDER_PROTOCOL = limitOrderProtocol;
}
/**
* @notice See {IOrderRegistrator-registerOrder}.
*/
function registerOrder(IOrderMixin.Order calldata order, bytes calldata extension, bytes calldata signature) external {
// Validate order
{
(bool valid, bytes4 validationResult) = order.isValidExtension(extension);
if (!valid) {
// solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(0, validationResult)
revert(0, 4)
}
}
}
// Validate signature
if(!ECDSA.recoverOrIsValidSignature(order.maker.get(), _LIMIT_ORDER_PROTOCOL.hashOrder(order), signature)) revert IOrderMixin.BadSignature();
emit OrderRegistered(order, extension, signature);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
type Address is uint256;
/**
* @notice AddressLib
* @notice Library for working with addresses encoded as uint256 values, which can include flags in the highest bits.
*/
library AddressLib {
uint256 private constant _LOW_160_BIT_MASK = (1 << 160) - 1;
/**
* @notice Returns the address representation of a uint256.
* @param a The uint256 value to convert to an address.
* @return The address representation of the provided uint256 value.
*/
function get(Address a) internal pure returns (address) {
return address(uint160(Address.unwrap(a) & _LOW_160_BIT_MASK));
}
/**
* @notice Checks if a given flag is set for the provided address.
* @param a The address to check for the flag.
* @param flag The flag to check for in the provided address.
* @return True if the provided flag is set in the address, false otherwise.
*/
function getFlag(Address a, uint256 flag) internal pure returns (bool) {
return (Address.unwrap(a) & flag) != 0;
}
/**
* @notice Returns a uint32 value stored at a specific bit offset in the provided address.
* @param a The address containing the uint32 value.
* @param offset The bit offset at which the uint32 value is stored.
* @return The uint32 value stored in the address at the specified bit offset.
*/
function getUint32(Address a, uint256 offset) internal pure returns (uint32) {
return uint32(Address.unwrap(a) >> offset);
}
/**
* @notice Returns a uint64 value stored at a specific bit offset in the provided address.
* @param a The address containing the uint64 value.
* @param offset The bit offset at which the uint64 value is stored.
* @return The uint64 value stored in the address at the specified bit offset.
*/
function getUint64(Address a, uint256 offset) internal pure returns (uint64) {
return uint64(Address.unwrap(a) >> offset);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
/**
* @title ECDSA signature operations
* @notice Provides functions for recovering addresses from signatures and verifying signatures, including support for EIP-2098 compact signatures.
*/
library ECDSA {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
uint256 private constant _S_BOUNDARY = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 + 1;
uint256 private constant _COMPACT_S_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
uint256 private constant _COMPACT_V_SHIFT = 255;
/**
* @notice Recovers the signer's address from the signature.
* @dev Recovers the address that has signed a hash with `(v, r, s)` signature.
* @param hash The keccak256 hash of the data signed.
* @param v The recovery byte of the signature.
* @param r The first 32 bytes of the signature.
* @param s The second 32 bytes of the signature.
* @return signer The address of the signer.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (address signer) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
if lt(s, _S_BOUNDARY) {
let ptr := mload(0x40)
mstore(ptr, hash)
mstore(add(ptr, 0x20), v)
mstore(add(ptr, 0x40), r)
mstore(add(ptr, 0x60), s)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
/**
* @notice Recovers the signer's address from the signature using `r` and `vs` components.
* @dev Recovers the address that has signed a hash with `r` and `vs`, where `vs` combines `v` and `s`.
* @param hash The keccak256 hash of the data signed.
* @param r The first 32 bytes of the signature.
* @param vs The combined `v` and `s` values of the signature.
* @return signer The address of the signer.
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (address signer) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let s := and(vs, _COMPACT_S_MASK)
if lt(s, _S_BOUNDARY) {
let ptr := mload(0x40)
mstore(ptr, hash)
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
mstore(add(ptr, 0x40), r)
mstore(add(ptr, 0x60), s)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
/**
* @notice Recovers the signer's address from a hash and a signature.
* @param hash The keccak256 hash of the signed data.
* @param signature The full signature from which the signer will be recovered.
* @return signer The address of the signer.
*/
/// @dev WARNING!!!
/// There is a known signature malleability issue with two representations of signatures!
/// Even though this function is able to verify both standard 65-byte and compact 64-byte EIP-2098 signatures
/// one should never use raw signatures for any kind of invalidation logic in their code.
/// As the standard and compact representations are interchangeable any invalidation logic that relies on
/// signature uniqueness will get rekt.
/// More info: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h
function recover(bytes32 hash, bytes calldata signature) internal view returns (address signer) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
// memory[ptr:ptr+0x80] = (hash, v, r, s)
switch signature.length
case 65 {
// memory[ptr+0x20:ptr+0x80] = (v, r, s)
mstore(add(ptr, 0x20), byte(0, calldataload(add(signature.offset, 0x40))))
calldatacopy(add(ptr, 0x40), signature.offset, 0x40)
}
case 64 {
// memory[ptr+0x20:ptr+0x80] = (v, r, s)
let vs := calldataload(add(signature.offset, 0x20))
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
calldatacopy(add(ptr, 0x40), signature.offset, 0x20)
mstore(add(ptr, 0x60), and(vs, _COMPACT_S_MASK))
}
default {
ptr := 0
}
if ptr {
if lt(mload(add(ptr, 0x60)), _S_BOUNDARY) {
// memory[ptr:ptr+0x20] = (hash)
mstore(ptr, hash)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
}
/**
* @notice Verifies the signature for a hash, either by recovering the signer or using EIP-1271's `isValidSignature` function.
* @dev Attempts to recover the signer's address from the signature; if the address is non-zero, checks if it's valid according to EIP-1271.
* @param signer The address to validate the signature against.
* @param hash The hash of the signed data.
* @param signature The signature to verify.
* @return success True if the signature is verified, false otherwise.
*/
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool success) {
if (signer == address(0)) return false;
if ((signature.length == 64 || signature.length == 65) && recover(hash, signature) == signer) {
return true;
}
return isValidSignature(signer, hash, signature);
}
/**
* @notice Verifies the signature for a hash, either by recovering the signer or using EIP-1271's `isValidSignature` function.
* @dev Attempts to recover the signer's address from the signature; if the address is non-zero, checks if it's valid according to EIP-1271.
* @param signer The address to validate the signature against.
* @param hash The hash of the signed data.
* @param v The recovery byte of the signature.
* @param r The first 32 bytes of the signature.
* @param s The second 32 bytes of the signature.
* @return success True if the signature is verified, false otherwise.
*/
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, v, r, s) == signer) {
return true;
}
return isValidSignature(signer, hash, v, r, s);
}
/**
* @notice Verifies the signature for a hash, either by recovering the signer or using EIP-1271's `isValidSignature` function.
* @dev Attempts to recover the signer's address from the signature; if the address is non-zero, checks if it's valid according to EIP-1271.
* @param signer The address to validate the signature against.
* @param hash The hash of the signed data.
* @param r The first 32 bytes of the signature.
* @param vs The combined `v` and `s` values of the signature.
* @return success True if the signature is verified, false otherwise.
*/
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, r, vs) == signer) {
return true;
}
return isValidSignature(signer, hash, r, vs);
}
/**
* @notice Verifies the signature for a given hash, attempting to recover the signer's address or validates it using EIP-1271 for 65-byte signatures.
* @dev Attempts to recover the signer's address from the signature. If the address is a contract, checks if the signature is valid according to EIP-1271.
* @param signer The expected signer's address.
* @param hash The keccak256 hash of the signed data.
* @param r The first 32 bytes of the signature.
* @param vs The last 32 bytes of the signature, with the last byte being the recovery id.
* @return success True if the signature is valid, false otherwise.
*/
function recoverOrIsValidSignature65(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, r, vs) == signer) {
return true;
}
return isValidSignature65(signer, hash, r, vs);
}
/**
* @notice Validates a signature for a hash using EIP-1271, if `signer` is a contract.
* @dev Makes a static call to `signer` with `isValidSignature` function selector from EIP-1271.
* @param signer The address of the signer to validate against, which could be an EOA or a contract.
* @param hash The hash of the signed data.
* @param signature The signature to validate.
* @return success True if the signature is valid according to EIP-1271, false otherwise.
*/
function isValidSignature(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature));
// return success && data.length == 32 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), signature.length)
calldatacopy(add(ptr, 0x64), signature.offset, signature.length)
if staticcall(gas(), signer, ptr, add(0x64, signature.length), 0, 0x20) {
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
}
}
}
/**
* @notice Validates a signature for a hash using EIP-1271, if `signer` is a contract.
* @dev Makes a static call to `signer` with `isValidSignature` function selector from EIP-1271.
* @param signer The address of the signer to validate against, which could be an EOA or a contract.
* @param hash The hash of the signed data.
* @param v The recovery byte of the signature.
* @param r The first 32 bytes of the signature.
* @param s The second 32 bytes of the signature.
* @return success True if the signature is valid according to EIP-1271, false otherwise.
*/
function isValidSignature(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
bytes4 selector = IERC1271.isValidSignature.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 65)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), s)
mstore8(add(ptr, 0xa4), v)
if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
}
}
}
/**
* @notice Validates a signature for a hash using EIP-1271, if `signer` is a contract.
* @dev Makes a static call to `signer` with `isValidSignature` function selector from EIP-1271.
* @param signer The address of the signer to validate against, which could be an EOA or a contract.
* @param hash The hash of the signed data.
* @param r The first 32 bytes of the signature.
* @param vs The last 32 bytes of the signature, with the last byte being the recovery id.
* @return success True if the signature is valid according to EIP-1271, false otherwise.
*/
function isValidSignature(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs)));
// return success && data.length == 32 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 64)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), vs)
if staticcall(gas(), signer, ptr, 0xa4, 0, 0x20) {
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
}
}
}
/**
* @notice Verifies if a 65-byte signature is valid for a given hash, according to EIP-1271.
* @param signer The address of the signer to validate against, which could be an EOA or a contract.
* @param hash The hash of the signed data.
* @param r The first 32 bytes of the signature.
* @param vs The combined `v` (recovery id) and `s` component of the signature, packed into the last 32 bytes.
* @return success True if the signature is valid according to EIP-1271, false otherwise.
*/
function isValidSignature65(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs & ~uint256(1 << 255), uint8(vs >> 255))));
// return success && data.length == 32 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 65)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), and(vs, _COMPACT_S_MASK))
mstore8(add(ptr, 0xa4), add(27, shr(_COMPACT_V_SHIFT, vs)))
if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
}
}
}
/**
* @notice Generates a hash compatible with Ethereum's signed message format.
* @dev Prepends the hash with Ethereum's message prefix before hashing it.
* @param hash The hash of the data to sign.
* @return res The Ethereum signed message hash.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 res) {
// 32 is the length in bytes of hash, enforced by the type signature above
// return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
mstore(0, 0x19457468657265756d205369676e6564204d6573736167653a0a333200000000) // "\x19Ethereum Signed Message:\n32"
mstore(28, hash)
res := keccak256(0, 60)
}
}
/**
* @notice Generates an EIP-712 compliant hash.
* @dev Encodes the domain separator and the struct hash according to EIP-712.
* @param domainSeparator The EIP-712 domain separator.
* @param structHash The EIP-712 struct hash.
* @return res The EIP-712 compliant hash.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 res) {
// return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, 0x1901000000000000000000000000000000000000000000000000000000000000) // "\x19\x01"
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
res := keccak256(ptr, 66)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.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 without `useBitInvalidator` gets cancelled
* @param orderHash Hash of the order
*/
event OrderCancelled(
bytes32 orderHash
);
/**
* @notice Emitted when order with `useBitInvalidator` gets cancelled
* @param maker Maker address
* @param slotIndex Slot index that was updated
* @param slotValue New slot value
*/
event BitInvalidatorUpdated(
address indexed maker,
uint256 slotIndex,
uint256 slotValue
);
/**
* @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 Inverse of the remaining amount of the order if order was filled at least once, 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);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import { IOrderMixin } from "./IOrderMixin.sol";
/**
* @title IOrderRegistrator
* @dev The interface defines the structure of the order registrator contract.
* The registrator is responsible for registering orders and emitting an event when an order is registered.
*/
interface IOrderRegistrator {
/**
* @notice Emitted when an order is registered.
* @param order The order that was registered.
* @param extension The extension data associated with the order.
* @param signature The signature of the order.
*/
event OrderRegistered(IOrderMixin.Order order, bytes extension, bytes signature);
/**
* @notice Registers an order.
* @param order The order to be registered.
* @param extension The extension data associated with the order.
* @param signature The signature of the order.
*/
function registerOrder(IOrderMixin.Order calldata order, bytes calldata extension, bytes calldata signature) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
/// @title The helper library to calculate linearly taker amount from maker amount and vice versa.
library AmountCalculatorLib {
/// @notice Calculates maker amount
/// @return Result Floored maker amount
function getMakingAmount(uint256 orderMakerAmount, uint256 orderTakerAmount, uint256 swapTakerAmount) internal pure returns(uint256) {
if ((swapTakerAmount | orderMakerAmount) >> 128 == 0) {
unchecked {
return (swapTakerAmount * orderMakerAmount) / orderTakerAmount;
}
}
return swapTakerAmount * orderMakerAmount / orderTakerAmount;
}
/// @notice Calculates taker amount
/// @return Result Ceiled taker amount
function getTakingAmount(uint256 orderMakerAmount, uint256 orderTakerAmount, uint256 swapMakerAmount) internal pure returns(uint256) {
if ((swapMakerAmount | orderTakerAmount) >> 128 == 0) {
unchecked {
return (swapMakerAmount * orderTakerAmount + orderMakerAmount - 1) / orderMakerAmount;
}
}
return (swapMakerAmount * orderTakerAmount + orderMakerAmount - 1) / orderMakerAmount;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IOrderMixin.sol";
import "./OffsetsLib.sol";
/**
* @title ExtensionLib
* @notice Library for retrieving extensions information for the IOrderMixin Interface.
*/
library ExtensionLib {
using AddressLib for Address;
using OffsetsLib for Offsets;
enum DynamicField {
MakerAssetSuffix,
TakerAssetSuffix,
MakingAmountData,
TakingAmountData,
Predicate,
MakerPermit,
PreInteractionData,
PostInteractionData,
CustomData
}
/**
* @notice Returns the MakerAssetSuffix from the provided extension calldata.
* @param extension The calldata from which the MakerAssetSuffix is to be retrieved.
* @return calldata Bytes representing the MakerAssetSuffix.
*/
function makerAssetSuffix(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.MakerAssetSuffix);
}
/**
* @notice Returns the TakerAssetSuffix from the provided extension calldata.
* @param extension The calldata from which the TakerAssetSuffix is to be retrieved.
* @return calldata Bytes representing the TakerAssetSuffix.
*/
function takerAssetSuffix(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.TakerAssetSuffix);
}
/**
* @notice Returns the MakingAmountData from the provided extension calldata.
* @param extension The calldata from which the MakingAmountData is to be retrieved.
* @return calldata Bytes representing the MakingAmountData.
*/
function makingAmountData(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.MakingAmountData);
}
/**
* @notice Returns the TakingAmountData from the provided extension calldata.
* @param extension The calldata from which the TakingAmountData is to be retrieved.
* @return calldata Bytes representing the TakingAmountData.
*/
function takingAmountData(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.TakingAmountData);
}
/**
* @notice Returns the order's predicate from the provided extension calldata.
* @param extension The calldata from which the predicate is to be retrieved.
* @return calldata Bytes representing the predicate.
*/
function predicate(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.Predicate);
}
/**
* @notice Returns the maker's permit from the provided extension calldata.
* @param extension The calldata from which the maker's permit is to be retrieved.
* @return calldata Bytes representing the maker's permit.
*/
function makerPermit(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.MakerPermit);
}
/**
* @notice Returns the pre-interaction from the provided extension calldata.
* @param extension The calldata from which the pre-interaction is to be retrieved.
* @return calldata Bytes representing the pre-interaction.
*/
function preInteractionTargetAndData(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.PreInteractionData);
}
/**
* @notice Returns the post-interaction from the provided extension calldata.
* @param extension The calldata from which the post-interaction is to be retrieved.
* @return calldata Bytes representing the post-interaction.
*/
function postInteractionTargetAndData(bytes calldata extension) internal pure returns(bytes calldata) {
return _get(extension, DynamicField.PostInteractionData);
}
/**
* @notice Returns extra suffix data from the provided extension calldata.
* @param extension The calldata from which the extra suffix data is to be retrieved.
* @return calldata Bytes representing the extra suffix data.
*/
function customData(bytes calldata extension) internal pure returns(bytes calldata) {
if (extension.length < 0x20) return msg.data[:0];
uint256 offsets = uint256(bytes32(extension));
unchecked {
return extension[0x20 + (offsets >> 224):];
}
}
/**
* @notice Retrieves a specific field from the provided extension calldata.
* @dev The first 32 bytes of an extension calldata contain offsets to the end of each field within the calldata.
* @param extension The calldata from which the field is to be retrieved.
* @param field The specific dynamic field to retrieve from the extension.
* @return calldata Bytes representing the requested field.
*/
function _get(bytes calldata extension, DynamicField field) private pure returns(bytes calldata) {
if (extension.length < 0x20) return msg.data[:0];
Offsets offsets;
bytes calldata concat;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
offsets := calldataload(extension.offset)
concat.offset := add(extension.offset, 0x20)
concat.length := sub(extension.length, 0x20)
}
return offsets.get(concat, uint256(field));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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
* 253 bit - unused
* 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 Returns the expiration time of the order.
* @param makerTraits The traits of the maker.
* @return result The expiration timestamp of the order.
*/
function getExpirationTime(MakerTraits makerTraits) internal pure returns (uint256) {
return (MakerTraits.unwrap(makerTraits) >> _EXPIRATION_OFFSET) & _EXPIRATION_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 = getExpirationTime(makerTraits);
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;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
type Offsets is uint256;
/// @title OffsetsLib
/// @dev A library for retrieving values by offsets from a concatenated calldata.
library OffsetsLib {
/// @dev Error to be thrown when the offset is out of bounds.
error OffsetOutOfBounds();
/**
* @notice Retrieves the field value calldata corresponding to the provided field index from the concatenated calldata.
* @dev
* The function performs the following steps:
* 1. Retrieve the start and end of the segment corresponding to the provided index from the offsets array.
* 2. Get the value from segment using offset and length calculated based on the start and end of the segment.
* 3. Throw `OffsetOutOfBounds` error if the length of the segment is greater than the length of the concatenated data.
* @param offsets The offsets encoding the start and end of each segment within the concatenated calldata.
* @param concat The concatenated calldata.
* @param index The index of the segment to retrieve. The field index 0 corresponds to the lowest bytes of the offsets array.
* @return result The calldata from a segment of the concatenated calldata corresponding to the provided index.
*/
function get(Offsets offsets, bytes calldata concat, uint256 index) internal pure returns(bytes calldata result) {
bytes4 exception = OffsetOutOfBounds.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let bitShift := shl(5, index) // bitShift = index * 32
let begin := and(0xffffffff, shr(bitShift, shl(32, offsets))) // begin = offsets[ bitShift : bitShift + 32 ]
let end := and(0xffffffff, shr(bitShift, offsets)) // end = offsets[ bitShift + 32 : bitShift + 64 ]
result.offset := add(concat.offset, begin)
result.length := sub(end, begin)
if gt(end, concat.length) {
mstore(0, exception)
revert(0, 4)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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.
* 251 bit `_ARGS_HAS_TARGET` - If set, then first 20 bytes of args are treated as target address for maker’s funds transfer.
* 224-247 bits `ARGS_EXTENSION_LENGTH` - The length of the extension calldata in the args.
* 200-223 bits `ARGS_INTERACTION_LENGTH` - The length of the interaction calldata in the args.
* 0-184 bits - 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;
/**
* @notice Checks if the args should contain target address.
* @param takerTraits The traits of the taker.
* @return result A boolean indicating whether the args should contain target address.
*/
function argsHasTarget(TakerTraits takerTraits) internal pure returns (bool) {
return (TakerTraits.unwrap(takerTraits) & _ARGS_HAS_TARGET) != 0;
}
/**
* @notice Retrieves the length of the extension calldata from the takerTraits.
* @param takerTraits The traits of the taker.
* @return result The length of the extension calldata encoded in the takerTraits.
*/
function argsExtensionLength(TakerTraits takerTraits) internal pure returns (uint256) {
return (TakerTraits.unwrap(takerTraits) >> _ARGS_EXTENSION_LENGTH_OFFSET) & _ARGS_EXTENSION_LENGTH_MASK;
}
/**
* @notice Retrieves the length of the interaction calldata from the takerTraits.
* @param takerTraits The traits of the taker.
* @return result The length of the interaction calldata encoded in the takerTraits.
*/
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;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import "@1inch/solidity-utils/contracts/libraries/ECDSA.sol";
import "@1inch/solidity-utils/contracts/libraries/AddressLib.sol";
import "./interfaces/IOrderMixin.sol";
import "./libraries/MakerTraitsLib.sol";
import "./libraries/ExtensionLib.sol";
import "./libraries/AmountCalculatorLib.sol";
import "./interfaces/IAmountGetter.sol";
/**
* @title OrderLib
* @dev The library provides common functionality for processing and manipulating limit orders.
* It provides functionality to calculate and verify order hashes, calculate trade amounts, and validate
* extension data associated with orders. The library also contains helper methods to get the receiver of
* an order and call getter functions.
*/
library OrderLib {
using AddressLib for Address;
using MakerTraitsLib for MakerTraits;
using ExtensionLib for bytes;
/// @dev Error to be thrown when the extension data of an order is missing.
error MissingOrderExtension();
/// @dev Error to be thrown when the order has an unexpected extension.
error UnexpectedOrderExtension();
/// @dev Error to be thrown when the order extension hash is invalid.
error InvalidExtensionHash();
/// @dev The typehash of the order struct.
bytes32 constant internal _LIMIT_ORDER_TYPEHASH = keccak256(
"Order("
"uint256 salt,"
"address maker,"
"address receiver,"
"address makerAsset,"
"address takerAsset,"
"uint256 makingAmount,"
"uint256 takingAmount,"
"uint256 makerTraits"
")"
);
uint256 constant internal _ORDER_STRUCT_SIZE = 0x100;
uint256 constant internal _DATA_HASH_SIZE = 0x120;
/**
* @notice Calculates the hash of an order.
* @param order The order to be hashed.
* @param domainSeparator The domain separator to be used for the EIP-712 hashing.
* @return result The keccak256 hash of the order data.
*/
function hash(IOrderMixin.Order calldata order, bytes32 domainSeparator) internal pure returns(bytes32 result) {
bytes32 typehash = _LIMIT_ORDER_TYPEHASH;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
// keccak256(abi.encode(_LIMIT_ORDER_TYPEHASH, order));
mstore(ptr, typehash)
calldatacopy(add(ptr, 0x20), order, _ORDER_STRUCT_SIZE)
result := keccak256(ptr, _DATA_HASH_SIZE)
}
result = ECDSA.toTypedDataHash(domainSeparator, result);
}
/**
* @notice Returns the receiver address for an order.
* @param order The order.
* @return receiver The address of the receiver, either explicitly defined in the order or the maker's address if not specified.
*/
function getReceiver(IOrderMixin.Order calldata order) internal pure returns(address /*receiver*/) {
address receiver = order.receiver.get();
return receiver != address(0) ? receiver : order.maker.get();
}
/**
* @notice Calculates the making amount based on the requested taking amount.
* @dev If getter is specified in the extension data, the getter is called to calculate the making amount,
* otherwise the making amount is calculated linearly.
* @param order The order.
* @param extension The extension data associated with the order.
* @param requestedTakingAmount The amount the taker wants to take.
* @param remainingMakingAmount The remaining amount of the asset left to fill.
* @param orderHash The hash of the order.
* @return makingAmount The amount of the asset the maker receives.
*/
function calculateMakingAmount(
IOrderMixin.Order calldata order,
bytes calldata extension,
uint256 requestedTakingAmount,
uint256 remainingMakingAmount,
bytes32 orderHash
) internal view returns(uint256) {
bytes calldata data = extension.makingAmountData();
if (data.length == 0) {
// Linear proportion
return AmountCalculatorLib.getMakingAmount(order.makingAmount, order.takingAmount, requestedTakingAmount);
}
return IAmountGetter(address(bytes20(data))).getMakingAmount(
order,
extension,
orderHash,
msg.sender,
requestedTakingAmount,
remainingMakingAmount,
data[20:]
);
}
/**
* @notice Calculates the taking amount based on the requested making amount.
* @dev If getter is specified in the extension data, the getter is called to calculate the taking amount,
* otherwise the taking amount is calculated linearly.
* @param order The order.
* @param extension The extension data associated with the order.
* @param requestedMakingAmount The amount the maker wants to receive.
* @param remainingMakingAmount The remaining amount of the asset left to be filled.
* @param orderHash The hash of the order.
* @return takingAmount The amount of the asset the taker takes.
*/
function calculateTakingAmount(
IOrderMixin.Order calldata order,
bytes calldata extension,
uint256 requestedMakingAmount,
uint256 remainingMakingAmount,
bytes32 orderHash
) internal view returns(uint256) {
bytes calldata data = extension.takingAmountData();
if (data.length == 0) {
// Linear proportion
return AmountCalculatorLib.getTakingAmount(order.makingAmount, order.takingAmount, requestedMakingAmount);
}
return IAmountGetter(address(bytes20(data))).getTakingAmount(
order,
extension,
orderHash,
msg.sender,
requestedMakingAmount,
remainingMakingAmount,
data[20:]
);
}
/**
* @dev Validates the extension associated with an order.
* @param order The order to validate against.
* @param extension The extension associated with the order.
* @return valid True if the extension is valid, false otherwise.
* @return errorSelector The error selector if the extension is invalid, 0x00000000 otherwise.
*/
function isValidExtension(IOrderMixin.Order calldata order, bytes calldata extension) internal pure returns(bool, bytes4) {
if (order.makerTraits.hasExtension()) {
if (extension.length == 0) return (false, MissingOrderExtension.selector);
// Lowest 160 bits of the order salt must be equal to the lowest 160 bits of the extension hash
if (uint256(keccak256(extension)) & type(uint160).max != order.salt & type(uint160).max) return (false, InvalidExtensionHash.selector);
} else {
if (extension.length > 0) return (false, UnexpectedOrderExtension.selector);
}
return (true, 0x00000000);
}
}{
"optimizer": {
"enabled": true,
"runs": 1000000
},
"evmVersion": "shanghai",
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IOrderMixin","name":"limitOrderProtocol","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadSignature","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"Address","name":"maker","type":"uint256"},{"internalType":"Address","name":"receiver","type":"uint256"},{"internalType":"Address","name":"makerAsset","type":"uint256"},{"internalType":"Address","name":"takerAsset","type":"uint256"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"MakerTraits","name":"makerTraits","type":"uint256"}],"indexed":false,"internalType":"struct IOrderMixin.Order","name":"order","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"extension","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"}],"name":"OrderRegistered","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"Address","name":"maker","type":"uint256"},{"internalType":"Address","name":"receiver","type":"uint256"},{"internalType":"Address","name":"makerAsset","type":"uint256"},{"internalType":"Address","name":"takerAsset","type":"uint256"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"MakerTraits","name":"makerTraits","type":"uint256"}],"internalType":"struct IOrderMixin.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"extension","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"registerOrder","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a03461006a57601f6106e738819003918201601f19168301916001600160401b0383118484101761006e5780849260209460405283398101031261006a57516001600160a01b038116810361006a57608052604051610664908161008382396080518161013a0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080604052600480361015610012575f80fd5b5f3560e01c63dfcb3e3414610025575f80fd5b3461027157610140367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0181811261027157610100809112610271576101049267ffffffffffffffff843581811161027157610084903690840161028f565b9091610124359081116102715761009e903690850161028f565b9390966100ab8385610369565b9015610288575073ffffffffffffffffffffffffffffffffffffffff602060405180937f802b2ef10000000000000000000000000000000000000000000000000000000082526101368683016004358152602435602082015260443560408201526064356060820152608435608082015260a43560a082015260c43560c082015260e060e435910152565b81847f0000000000000000000000000000000000000000000000000000000000000000165afa90811561027d5786918a915f9161023e575b61017c9450602435166104a5565b156102165750916102027f1e8610b3a2275f01a103e27257e911d890537b0c70578537ea077ec0a27b5bc9969261021194876040519889986101f78a6004358152602435602082015260443560408201526064356060820152608435608082015260a43560a082015260c43560c082015260e060e435910152565b89015287019161032b565b9184830361012086015261032b565b0390a1005b6040517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b925050506020823d602011610275575b8161025b602093836102bd565b810103126102715788869161017c93519061016e565b5f80fd5b3d915061024e565b6040513d5f823e3d90fd5b90505f525ffd5b9181601f840112156102715782359167ffffffffffffffff8311610271576020838186019501011161027157565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102fe57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b9060e4357f020000000000000000000000000000000000000000000000000000000000000016156104785780156104505767ffffffffffffffff81116102fe57604051906103df60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601836102bd565b8082526020820192368282011161027157815f9260209286378301015273ffffffffffffffffffffffffffffffffffffffff9182915190201690600435160361042a575b6001905f90565b5f907fdc11ee6b0000000000000000000000000000000000000000000000000000000090565b50505f907fb2d25e490000000000000000000000000000000000000000000000000000000090565b905015610423575f907f74896a7b0000000000000000000000000000000000000000000000000000000090565b90919273ffffffffffffffffffffffffffffffffffffffff9182811692831561062457604093848414918215610619575b8261054c575b505061054257602092825f9384978351937f1626ba7e0000000000000000000000000000000000000000000000000000000098898652600486015260248501528160448501526064840137606401915afa610535575090565b5f51143d60201416919050565b5050505050600190565b9091505f85518580604114610601576040146105bc57505f805b610575575b5016145f806104dc565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16060820151101561056b5760209150608081895f935282805260015afa505f515f61056b565b807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208b01358060ff1c601b01602084015260208c8b850137166060820152610566565b50868901355f1a602082015280878a81830137610566565b6041851492506104d6565b5050505050505f9056fea264697066735822122054e96ab7ad42ec0b6ed2f0ea0c086f431607ccc6765983df684579d449a7e85564736f6c63430008170033000000000000000000000000111111125421ca6dc452d289314280a0f8842a65
Deployed Bytecode
0x6080604052600480361015610012575f80fd5b5f3560e01c63dfcb3e3414610025575f80fd5b3461027157610140367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0181811261027157610100809112610271576101049267ffffffffffffffff843581811161027157610084903690840161028f565b9091610124359081116102715761009e903690850161028f565b9390966100ab8385610369565b9015610288575073ffffffffffffffffffffffffffffffffffffffff602060405180937f802b2ef10000000000000000000000000000000000000000000000000000000082526101368683016004358152602435602082015260443560408201526064356060820152608435608082015260a43560a082015260c43560c082015260e060e435910152565b81847f000000000000000000000000111111125421ca6dc452d289314280a0f8842a65165afa90811561027d5786918a915f9161023e575b61017c9450602435166104a5565b156102165750916102027f1e8610b3a2275f01a103e27257e911d890537b0c70578537ea077ec0a27b5bc9969261021194876040519889986101f78a6004358152602435602082015260443560408201526064356060820152608435608082015260a43560a082015260c43560c082015260e060e435910152565b89015287019161032b565b9184830361012086015261032b565b0390a1005b6040517f5cd5d233000000000000000000000000000000000000000000000000000000008152fd5b925050506020823d602011610275575b8161025b602093836102bd565b810103126102715788869161017c93519061016e565b5f80fd5b3d915061024e565b6040513d5f823e3d90fd5b90505f525ffd5b9181601f840112156102715782359167ffffffffffffffff8311610271576020838186019501011161027157565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102fe57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b9060e4357f020000000000000000000000000000000000000000000000000000000000000016156104785780156104505767ffffffffffffffff81116102fe57604051906103df60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601836102bd565b8082526020820192368282011161027157815f9260209286378301015273ffffffffffffffffffffffffffffffffffffffff9182915190201690600435160361042a575b6001905f90565b5f907fdc11ee6b0000000000000000000000000000000000000000000000000000000090565b50505f907fb2d25e490000000000000000000000000000000000000000000000000000000090565b905015610423575f907f74896a7b0000000000000000000000000000000000000000000000000000000090565b90919273ffffffffffffffffffffffffffffffffffffffff9182811692831561062457604093848414918215610619575b8261054c575b505061054257602092825f9384978351937f1626ba7e0000000000000000000000000000000000000000000000000000000098898652600486015260248501528160448501526064840137606401915afa610535575090565b5f51143d60201416919050565b5050505050600190565b9091505f85518580604114610601576040146105bc57505f805b610575575b5016145f806104dc565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16060820151101561056b5760209150608081895f935282805260015afa505f515f61056b565b807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208b01358060ff1c601b01602084015260208c8b850137166060820152610566565b50868901355f1a602082015280878a81830137610566565b6041851492506104d6565b5050505050505f9056fea264697066735822122054e96ab7ad42ec0b6ed2f0ea0c086f431607ccc6765983df684579d449a7e85564736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000111111125421ca6dc452d289314280a0f8842a65
-----Decoded View---------------
Arg [0] : limitOrderProtocol (address): 0x111111125421cA6dc452d289314280a0f8842A65
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000111111125421ca6dc452d289314280a0f8842a65
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.