Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Settlement
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@1inch/limit-order-protocol-contract/contracts/interfaces/IOrderMixin.sol";
import "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";
import "./interfaces/ISettlement.sol";
import "./interfaces/IResolver.sol";
import "./libraries/DynamicSuffix.sol";
import "./libraries/OrderSaltParser.sol";
import "./libraries/OrderSuffix.sol";
import "./FeeBankCharger.sol";
contract Settlement is ISettlement, FeeBankCharger {
using SafeERC20 for IERC20;
using OrderSaltParser for uint256;
using DynamicSuffix for bytes;
using AddressLib for Address;
using OrderSuffix for OrderLib.Order;
using TakingFee for TakingFee.Data;
error AccessDenied();
error IncorrectCalldataParams();
error FailedExternalCall();
error ResolverIsNotWhitelisted();
error WrongInteractionTarget();
bytes1 private constant _FINALIZE_INTERACTION = 0x01;
uint256 private constant _ORDER_FEE_BASE_POINTS = 1e15;
uint256 private constant _BASE_POINTS = 10_000_000; // 100%
IOrderMixin private immutable _limitOrderProtocol;
modifier onlyThis(address account) {
if (account != address(this)) revert AccessDenied();
_;
}
modifier onlyLimitOrderProtocol {
if (msg.sender != address(_limitOrderProtocol)) revert AccessDenied();
_;
}
constructor(IOrderMixin limitOrderProtocol, IERC20 token)
FeeBankCharger(token)
{
_limitOrderProtocol = limitOrderProtocol;
}
function settleOrders(bytes calldata data) external {
_settleOrder(data, msg.sender, 0, new bytes(0));
}
function fillOrderInteraction(
address taker,
uint256, /* makingAmount */
uint256 takingAmount,
bytes calldata interactiveData
) external onlyThis(taker) onlyLimitOrderProtocol returns (uint256 result) {
(DynamicSuffix.Data calldata suffix, bytes calldata tokensAndAmounts, bytes calldata interaction) = interactiveData.decodeSuffix();
IERC20 token = IERC20(suffix.token.get());
result = takingAmount * (_BASE_POINTS + suffix.rateBump) / _BASE_POINTS;
uint256 takingFee = result * suffix.takingFee.ratio() / TakingFee._TAKING_FEE_BASE;
bytes memory allTokensAndAmounts = new bytes(tokensAndAmounts.length + 0x40);
assembly {
let ptr := add(allTokensAndAmounts, 0x20)
calldatacopy(ptr, tokensAndAmounts.offset, tokensAndAmounts.length)
ptr := add(ptr, tokensAndAmounts.length)
mstore(ptr, token)
mstore(add(ptr, 0x20), add(result, takingFee))
}
if (interactiveData[0] == _FINALIZE_INTERACTION) {
_chargeFee(suffix.resolver.get(), suffix.totalFee);
address target = address(bytes20(interaction));
bytes calldata data = interaction[20:];
IResolver(target).resolveOrders(suffix.resolver.get(), allTokensAndAmounts, data);
} else {
_settleOrder(
interaction,
suffix.resolver.get(),
suffix.totalFee,
allTokensAndAmounts
);
}
if (takingFee > 0) {
token.safeTransfer(suffix.takingFee.receiver(), takingFee);
}
token.forceApprove(address(_limitOrderProtocol), result);
}
bytes4 private constant _FILL_ORDER_TO_SELECTOR = 0xe5d7bde6; // IOrderMixin.fillOrderTo.selector
bytes4 private constant _WRONG_INTERACTION_TARGET_SELECTOR = 0x5b34bf89; // WrongInteractionTarget.selector
function _settleOrder(bytes calldata data, address resolver, uint256 totalFee, bytes memory tokensAndAmounts) private {
OrderLib.Order calldata order;
assembly {
order := add(data.offset, calldataload(data.offset))
}
if (!order.checkResolver(resolver)) revert ResolverIsNotWhitelisted();
TakingFee.Data takingFeeData = order.takingFee();
totalFee += order.salt.getFee() * _ORDER_FEE_BASE_POINTS;
uint256 rateBump = order.rateBump();
uint256 suffixLength = DynamicSuffix._STATIC_DATA_SIZE + tokensAndAmounts.length + 0x20;
IOrderMixin limitOrderProtocol = _limitOrderProtocol;
assembly {
function memcpy(dst, src, len) {
pop(staticcall(gas(), 0x4, src, len, dst, len))
}
let interactionLengthOffset := calldataload(add(data.offset, 0x40))
let interactionOffset := add(interactionLengthOffset, 0x20)
let interactionLength := calldataload(add(data.offset, interactionLengthOffset))
{ // stack too deep
let target := shr(96, calldataload(add(data.offset, interactionOffset)))
if or(lt(interactionLength, 20), iszero(eq(target, address()))) {
mstore(0, _WRONG_INTERACTION_TARGET_SELECTOR)
revert(0, 4)
}
}
// Copy calldata and patch interaction.length
let ptr := mload(0x40)
mstore(ptr, _FILL_ORDER_TO_SELECTOR)
calldatacopy(add(ptr, 4), data.offset, data.length)
mstore(add(add(ptr, interactionLengthOffset), 4), add(interactionLength, suffixLength))
{ // stack too deep
// Append suffix fields
let offset := add(add(ptr, interactionOffset), interactionLength)
mstore(add(offset, 0x04), totalFee)
mstore(add(offset, 0x24), resolver)
mstore(add(offset, 0x44), calldataload(add(order, 0x40))) // takerAsset
mstore(add(offset, 0x64), rateBump)
mstore(add(offset, 0x84), takingFeeData)
let tokensAndAmountsLength := mload(tokensAndAmounts)
memcpy(add(offset, 0xa4), add(tokensAndAmounts, 0x20), tokensAndAmountsLength)
mstore(add(offset, add(0xa4, tokensAndAmountsLength)), tokensAndAmountsLength)
}
// Call fillOrderTo
if iszero(call(gas(), limitOrderProtocol, 0, ptr, add(add(4, suffixLength), data.length), ptr, 0)) {
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
pragma abicoder v1;
/**
* @title Interface for interactor which acts after `taker -> maker` transfers.
* @notice The order filling steps are `preInteraction` =>` Transfer "maker -> taker"` => **`Interaction`** => `Transfer "taker -> maker"` => `postInteraction`
*/
interface IInteractionNotificationReceiver {
/**
* @notice Callback method that gets called after all funds transfers
* @param taker Taker address (tx sender)
* @param makingAmount Actual making amount
* @param takingAmount Actual taking amount
* @param interactionData Interaction calldata
* @return offeredTakingAmount Suggested amount. Order is filled with this amount if maker or taker getter functions are not defined.
*/
function fillOrderInteraction(
address taker,
uint256 makingAmount,
uint256 takingAmount,
bytes memory interactionData
) external returns(uint256 offeredTakingAmount);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "../OrderLib.sol";
interface IOrderMixin {
/**
* @notice Returns unfilled amount for order. Throws if order does not exist
* @param orderHash Order's hash. Can be obtained by the `hashOrder` function
* @return amount Unfilled amount
*/
function remaining(bytes32 orderHash) external view returns(uint256 amount);
/**
* @notice Returns unfilled amount for order
* @param orderHash Order's hash. Can be obtained by the `hashOrder` function
* @return rawAmount Unfilled amount of order plus one if order exists. Otherwise 0
*/
function remainingRaw(bytes32 orderHash) external view returns(uint256 rawAmount);
/**
* @notice Same as `remainingRaw` but for multiple orders
* @param orderHashes Array of hashes
* @return rawAmounts Array of amounts for each order plus one if order exists or 0 otherwise
*/
function remainingsRaw(bytes32[] memory orderHashes) external view returns(uint256[] memory rawAmounts);
/**
* @notice Checks order predicate
* @param order Order to check predicate for
* @return result Predicate evaluation result. True if predicate allows to fill the order, false otherwise
*/
function checkPredicate(OrderLib.Order calldata order) external view returns(bool result);
/**
* @notice Returns order hash according to EIP712 standard
* @param order Order to get hash for
* @return orderHash Hash of the order
*/
function hashOrder(OrderLib.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 Cancels order.
* @dev Order is cancelled by setting remaining amount to _ORDER_FILLED value
* @param order Order quote to cancel
* @return orderRemaining Unfilled amount of order before cancellation
* @return orderHash Hash of the filled order
*/
function cancelOrder(OrderLib.Order calldata order) external returns(uint256 orderRemaining, bytes32 orderHash);
/**
* @notice Fills an order. If one doesn't exist (first fill) it will be created using order.makerAssetData
* @param order Order quote to fill
* @param signature Signature to confirm quote ownership
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param makingAmount Making amount
* @param takingAmount Taking amount
* @param skipPermitAndThresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount. Top-most bit specifies whether taker wants to skip maker's permit.
* @return actualMakingAmount Actual amount transferred from maker to taker
* @return actualTakingAmount Actual amount transferred from taker to maker
* @return orderHash Hash of the filled order
*/
function fillOrder(
OrderLib.Order calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 makingAmount,
uint256 takingAmount,
uint256 skipPermitAndThresholdAmount
) external payable returns(uint256 actualMakingAmount, uint256 actualTakingAmount, bytes32 orderHash);
/**
* @notice Same as `fillOrderTo` but calls permit first,
* allowing to approve token spending and make a swap in one transaction.
* Also allows to specify funds destination instead of `msg.sender`
* @dev See tests for examples
* @param order Order quote to fill
* @param signature Signature to confirm quote ownership
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param makingAmount Making amount
* @param takingAmount Taking amount
* @param skipPermitAndThresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount. Top-most bit specifies whether taker wants to skip maker's permit.
* @param target Address that will receive swap funds
* @param permit Should consist of abiencoded token address and encoded `IERC20Permit.permit` call.
* @return actualMakingAmount Actual amount transferred from maker to taker
* @return actualTakingAmount Actual amount transferred from taker to maker
* @return orderHash Hash of the filled order
*/
function fillOrderToWithPermit(
OrderLib.Order calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 makingAmount,
uint256 takingAmount,
uint256 skipPermitAndThresholdAmount,
address target,
bytes calldata permit
) external returns(uint256 actualMakingAmount, uint256 actualTakingAmount, bytes32 orderHash);
/**
* @notice Same as `fillOrder` but allows to specify funds destination instead of `msg.sender`
* @param order_ Order quote to fill
* @param signature Signature to confirm quote ownership
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param makingAmount Making amount
* @param takingAmount Taking amount
* @param skipPermitAndThresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount. Top-most bit specifies whether taker wants to skip maker's permit.
* @param target Address that will receive swap funds
* @return actualMakingAmount Actual amount transferred from maker to taker
* @return actualTakingAmount Actual amount transferred from taker to maker
* @return orderHash Hash of the filled order
*/
function fillOrderTo(
OrderLib.Order calldata order_,
bytes calldata signature,
bytes calldata interaction,
uint256 makingAmount,
uint256 takingAmount,
uint256 skipPermitAndThresholdAmount,
address target
) external payable returns(uint256 actualMakingAmount, uint256 actualTakingAmount, bytes32 orderHash);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@1inch/solidity-utils/contracts/libraries/ECDSA.sol";
library OrderLib {
struct Order {
uint256 salt;
address makerAsset;
address takerAsset;
address maker;
address receiver;
address allowedSender; // equals to Zero address on public orders
uint256 makingAmount;
uint256 takingAmount;
uint256 offsets;
// bytes makerAssetData;
// bytes takerAssetData;
// bytes getMakingAmount; // this.staticcall(abi.encodePacked(bytes, swapTakerAmount)) => (swapMakerAmount)
// bytes getTakingAmount; // this.staticcall(abi.encodePacked(bytes, swapMakerAmount)) => (swapTakerAmount)
// bytes predicate; // this.staticcall(bytes) => (bool)
// bytes permit; // On first fill: permit.1.call(abi.encodePacked(permit.selector, permit.2))
// bytes preInteraction;
// bytes postInteraction;
bytes interactions; // concat(makerAssetData, takerAssetData, getMakingAmount, getTakingAmount, predicate, permit, preIntercation, postInteraction)
}
bytes32 constant internal _LIMIT_ORDER_TYPEHASH = keccak256(
"Order("
"uint256 salt,"
"address makerAsset,"
"address takerAsset,"
"address maker,"
"address receiver,"
"address allowedSender,"
"uint256 makingAmount,"
"uint256 takingAmount,"
"uint256 offsets,"
"bytes interactions"
")"
);
enum DynamicField {
MakerAssetData,
TakerAssetData,
GetMakingAmount,
GetTakingAmount,
Predicate,
Permit,
PreInteraction,
PostInteraction
}
function getterIsFrozen(bytes calldata getter) internal pure returns(bool) {
return getter.length == 1 && getter[0] == "x";
}
function _get(Order calldata order, DynamicField field) private pure returns(bytes calldata) {
uint256 bitShift = uint256(field) << 5; // field * 32
return order.interactions[
uint32((order.offsets << 32) >> bitShift):
uint32(order.offsets >> bitShift)
];
}
function makerAssetData(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.MakerAssetData);
}
function takerAssetData(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.TakerAssetData);
}
function getMakingAmount(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.GetMakingAmount);
}
function getTakingAmount(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.GetTakingAmount);
}
function predicate(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.Predicate);
}
function permit(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.Permit);
}
function preInteraction(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.PreInteraction);
}
function postInteraction(Order calldata order) internal pure returns(bytes calldata) {
return _get(order, DynamicField.PostInteraction);
}
function hash(Order calldata order, bytes32 domainSeparator) internal pure returns(bytes32 result) {
bytes calldata interactions = order.interactions;
bytes32 typehash = _LIMIT_ORDER_TYPEHASH;
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
// keccak256(abi.encode(_LIMIT_ORDER_TYPEHASH, orderWithoutInteractions, keccak256(order.interactions)));
calldatacopy(ptr, interactions.offset, interactions.length)
mstore(add(ptr, 0x140), keccak256(ptr, interactions.length))
calldatacopy(add(ptr, 0x20), order, 0x120)
mstore(ptr, typehash)
result := keccak256(ptr, 0x160)
}
result = ECDSA.toTypedDataHash(domainSeparator, result);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
interface IDaiLikePermit {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
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;
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (address signer) {
/// @solidity memory-safe-assembly
assembly { // 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)
}
}
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (address signer) {
/// @solidity memory-safe-assembly
assembly { // 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)
}
}
}
/// @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) {
/// @solidity memory-safe-assembly
assembly { // 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)
}
}
}
}
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);
}
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);
}
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);
}
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);
}
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 >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly { // 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))
}
}
}
function isValidSignature(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly { // 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))
}
}
}
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 >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly { // 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))
}
}
}
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 >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly { // 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))
}
}
}
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));
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
mstore(0, 0x19457468657265756d205369676e6564204d6573736167653a0a333200000000) // "\x19Ethereum Signed Message:\n32"
mstore(28, hash)
res := keccak256(0, 60)
}
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 res) {
// return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
/// @solidity memory-safe-assembly
assembly { // 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
pragma solidity ^0.8.0;
pragma abicoder v1;
/// @title Revert reason forwarder.
library RevertReasonForwarder {
/// @dev Forwards latest externall call revert.
function reRevert() internal pure {
// bubble up revert reason from latest external call
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "../interfaces/IDaiLikePermit.sol";
import "../libraries/RevertReasonForwarder.sol";
/// @title Implements efficient safe methods for ERC20 interface.
library SafeERC20 {
error SafeTransferFailed();
error SafeTransferFromFailed();
error ForceApproveFailed();
error SafeIncreaseAllowanceFailed();
error SafeDecreaseAllowanceFailed();
error SafePermitBadLength();
/// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
bytes4 selector = token.transferFrom.selector;
bool success;
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
success := call(gas(), token, 0, data, 100, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
if (!success) revert SafeTransferFromFailed();
}
/// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
if (!_makeCall(token, token.transfer.selector, to, value)) {
revert SafeTransferFailed();
}
}
/// @dev If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry.
function forceApprove(
IERC20 token,
address spender,
uint256 value
) internal {
if (!_makeCall(token, token.approve.selector, spender, value)) {
if (
!_makeCall(token, token.approve.selector, spender, 0) ||
!_makeCall(token, token.approve.selector, spender, value)
) {
revert ForceApproveFailed();
}
}
}
/// @dev Allowance increase with safe math check.
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();
forceApprove(token, spender, allowance + value);
}
/// @dev Allowance decrease with safe math check.
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > allowance) revert SafeDecreaseAllowanceFailed();
forceApprove(token, spender, allowance - value);
}
/// @dev Calls either ERC20 or Dai `permit` for `token`, if unsuccessful forwards revert from external call.
function safePermit(IERC20 token, bytes calldata permit) internal {
if (!tryPermit(token, permit)) RevertReasonForwarder.reRevert();
}
function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool) {
if (permit.length == 32 * 7) {
return _makeCalldataCall(token, IERC20Permit.permit.selector, permit);
}
if (permit.length == 32 * 8) {
return _makeCalldataCall(token, IDaiLikePermit.permit.selector, permit);
}
revert SafePermitBadLength();
}
function _makeCall(
IERC20 token,
bytes4 selector,
address to,
uint256 amount
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), to)
mstore(add(data, 0x24), amount)
success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
function _makeCalldataCall(
IERC20 token,
bytes4 selector,
bytes calldata args
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly { // solhint-disable-line no-inline-assembly
let len := add(4, args.length)
let data := mload(0x40)
mstore(data, selector)
calldatacopy(add(data, 0x04), args.offset, args.length)
success := call(gas(), token, 0, data, len, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
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
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IFeeBankCharger.sol";
import "./interfaces/IFeeBank.sol";
/// @title Contract with fee mechanism for solvers to pay for using the system
contract FeeBank is IFeeBank, Ownable {
using SafeERC20 for IERC20;
IERC20 private immutable _token;
IFeeBankCharger private immutable _charger;
mapping(address => uint256) private _accountDeposits;
constructor(IFeeBankCharger charger, IERC20 inch, address owner) {
_charger = charger;
_token = inch;
transferOwnership(owner);
}
function availableCredit(address account) external view returns (uint256) {
return _charger.availableCredit(account);
}
/**
* @notice Increment sender's availableCredit in Settlement contract.
* @param amount The amount of 1INCH sender pay for incresing.
* @return totalAvailableCredit The total sender's availableCredit after deposit.
*/
function deposit(uint256 amount) external returns (uint256 totalAvailableCredit) {
return _depositFor(msg.sender, amount);
}
/**
* @notice Increases account's availableCredit in Settlement contract.
* @param account The account whose availableCredit is increased by the sender.
* @param amount The amount of 1INCH sender pay for incresing.
* @return totalAvailableCredit The total account's availableCredit after deposit.
*/
function depositFor(address account, uint256 amount) external returns (uint256 totalAvailableCredit) {
return _depositFor(account, amount);
}
/**
* @notice See {deposit}. This method uses permit for deposit without prior approves.
* @param amount The amount of 1INCH sender pay for incresing.
* @param permit The data with sender's permission via token.
* @return totalAvailableCredit The total sender's availableCredit after deposit.
*/
function depositWithPermit(uint256 amount, bytes calldata permit) external returns (uint256 totalAvailableCredit) {
return depositForWithPermit(msg.sender, amount, permit);
}
/**
* @notice See {depositFor} and {depositWithPermit}.
*/
function depositForWithPermit(
address account,
uint256 amount,
bytes calldata permit
) public returns (uint256 totalAvailableCredit) {
_token.safePermit(permit);
return _depositFor(account, amount);
}
/**
* @notice Returns unspent availableCredit.
* @param amount The amount of 1INCH sender returns.
* @return totalAvailableCredit The total sender's availableCredit after withdrawal.
*/
function withdraw(uint256 amount) external returns (uint256 totalAvailableCredit) {
return _withdrawTo(msg.sender, amount);
}
/**
* @notice Returns unspent availableCredit to specific account.
* @param account The account which get withdrawaled tokens.
* @param amount The amount of withdrawaled tokens.
* @return totalAvailableCredit The total sender's availableCredit after withdrawal.
*/
function withdrawTo(address account, uint256 amount) external returns (uint256 totalAvailableCredit) {
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[] memory accounts) external onlyOwner returns (uint256 totalAccountFees) {
uint256 accountsLength = accounts.length;
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_;
}
_token.safeTransfer(msg.sender, totalAccountFees);
}
function _depositFor(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) {
_token.safeTransferFrom(msg.sender, address(this), amount);
_accountDeposits[account] += amount;
totalAvailableCredit = _charger.increaseAvailableCredit(account, amount);
}
function _withdrawTo(address account, uint256 amount) internal returns (uint256 totalAvailableCredit) {
totalAvailableCredit = _charger.decreaseAvailableCredit(msg.sender, amount);
_accountDeposits[msg.sender] -= amount;
_token.safeTransfer(account, amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IFeeBankCharger.sol";
import "./FeeBank.sol";
contract FeeBankCharger is IFeeBankCharger {
error OnlyFeeBankAccess();
error NotEnoughCredit();
IFeeBank public immutable feeBank;
mapping(address => uint256) private _creditAllowance;
modifier onlyFeeBank() {
if (msg.sender != address(feeBank)) revert OnlyFeeBankAccess();
_;
}
constructor(IERC20 token) {
feeBank = new FeeBank(this, token, msg.sender);
}
function availableCredit(address account) external view returns (uint256) {
return _creditAllowance[account];
}
function increaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) {
allowance = _creditAllowance[account];
allowance += amount;
_creditAllowance[account] = allowance;
}
function decreaseAvailableCredit(address account, uint256 amount) external onlyFeeBank returns (uint256 allowance) {
allowance = _creditAllowance[account];
allowance -= amount;
_creditAllowance[account] = allowance;
}
function _chargeFee(address account, uint256 fee) internal {
if (fee > 0) {
uint256 currentAllowance = _creditAllowance[account];
if (currentAllowance < fee) revert NotEnoughCredit();
unchecked {
_creditAllowance[account] = currentAllowance - fee;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IFeeBank {
function deposit(uint256 amount) external returns (uint256 totalAvailableCredit);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IFeeBankCharger {
function availableCredit(address account) external view returns (uint256);
function increaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance);
function decreaseAvailableCredit(address account, uint256 amount) external returns (uint256 allowance);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "../libraries/DynamicSuffix.sol";
interface IResolver {
function resolveOrders(address resolver, bytes calldata tokensAndAmounts, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@1inch/limit-order-protocol-contract/contracts/interfaces/IInteractionNotificationReceiver.sol";
import "./IFeeBankCharger.sol";
interface ISettlement is IInteractionNotificationReceiver, IFeeBankCharger {
function settleOrders(bytes calldata order) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
type Address is uint256;
library AddressLib {
function get(Address a) internal pure returns (address) {
return address(uint160(Address.unwrap(a)));
}
function getFlag(Address a, uint256 flag) internal pure returns (bool) {
return Address.unwrap(a) & flag != 0;
}
function getUint32(Address a, uint256 offset) internal pure returns (uint32) {
return uint32(Address.unwrap(a) >> 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.17;
import "./Address.sol";
import "./TakingFee.sol";
// layout of dynamic suffix is as follows:
// 0x00 - 0x19: totalFee
// 0x20 - 0x39: resolver
// 0x40 - 0x59: token
// 0x60 - 0x79: rateBump
// 0x80 - 0x99: takingFee
// 0xa0 - 0x..: tokensAndAmounts bytes
// 0x.. - 0x..: tokensAndAmounts length in bytes
library DynamicSuffix {
struct Data {
uint256 totalFee;
Address resolver;
Address token;
uint256 rateBump;
TakingFee.Data takingFee;
}
uint256 internal constant _STATIC_DATA_SIZE = 0xa0;
function decodeSuffix(bytes calldata cd) internal pure returns(Data calldata suffix, bytes calldata tokensAndAmounts, bytes calldata interaction) {
assembly {
let lengthOffset := sub(add(cd.offset, cd.length), 0x20)
tokensAndAmounts.length := calldataload(lengthOffset)
tokensAndAmounts.offset := sub(lengthOffset, tokensAndAmounts.length)
suffix := sub(tokensAndAmounts.offset, _STATIC_DATA_SIZE)
interaction.offset := add(cd.offset, 1)
interaction.length := sub(suffix, interaction.offset)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @title Library for parsing parameters from salt.
library OrderSaltParser {
uint256 private constant _TIME_START_MASK = 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000; // prettier-ignore
uint256 private constant _DURATION_MASK = 0x00000000FFFFFF00000000000000000000000000000000000000000000000000; // prettier-ignore
uint256 private constant _INITIAL_RATE_BUMP_MASK = 0x00000000000000FFFFFF00000000000000000000000000000000000000000000; // prettier-ignore
uint256 private constant _FEE_MASK = 0x00000000000000000000FFFFFFFF000000000000000000000000000000000000; // prettier-ignore
uint256 private constant _SALT_MASK = 0x0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore
uint256 private constant _TIME_START_SHIFT = 224; // orderTimeMask 224-255
uint256 private constant _DURATION_SHIFT = 200; // durationMask 200-223
uint256 private constant _INITIAL_RATE_BUMP_SHIFT = 176; // initialRateMask 176-200
uint256 private constant _FEE_SHIFT = 144; // orderFee 144-175
function getStartTime(uint256 salt) internal pure returns (uint256) {
return (salt & _TIME_START_MASK) >> _TIME_START_SHIFT;
}
function getDuration(uint256 salt) internal pure returns (uint256) {
return (salt & _DURATION_MASK) >> _DURATION_SHIFT;
}
function getInitialRateBump(uint256 salt) internal pure returns (uint256) {
return (salt & _INITIAL_RATE_BUMP_MASK) >> _INITIAL_RATE_BUMP_SHIFT;
}
function getFee(uint256 salt) internal pure returns (uint256) {
return (salt & _FEE_MASK) >> _FEE_SHIFT;
}
function getSalt(uint256 salt) internal pure returns (uint256) {
return salt & _SALT_MASK;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@1inch/limit-order-protocol-contract/contracts/OrderLib.sol";
import "./OrderSaltParser.sol";
import "./TakingFee.sol";
// Placed in the end of the order interactions data
// Last byte contains flags and lengths, can have up to 15 resolvers and 7 points
library OrderSuffix {
using OrderSaltParser for uint256;
// `Order.interactions` suffix structure:
// M*(1 + 3 bytes) - auction points coefficients with seconds delays
// N*(4 + 20 bytes) - resolver with corresponding time limit
// 4 bytes - public time limit
// 32 bytes - taking fee (optional if flags has _HAS_TAKING_FEE_FLAG)
// 1 bytes - flags
uint256 private constant _HAS_TAKING_FEE_FLAG = 0x80;
uint256 private constant _RESOLVERS_LENGTH_MASK = 0x78;
uint256 private constant _RESOLVERS_LENGTH_BIT_SHIFT = 3;
uint256 private constant _POINTS_LENGTH_MASK = 0x07;
uint256 private constant _POINTS_LENGTH_BIT_SHIFT = 0;
uint256 private constant _TAKING_FEE_BYTES_SIZE = 32;
uint256 private constant _PUBLIC_TIME_LIMIT_BYTES_SIZE = 4;
uint256 private constant _PUBLIC_TIME_LIMIT_BIT_SHIFT = 224; // 256 - _PUBLIC_TIME_LIMIT_BYTES_SIZE * 8
uint256 private constant _AUCTION_POINT_DELAY_BYTES_SIZE = 2;
uint256 private constant _AUCTION_POINT_BUMP_BYTES_SIZE = 3;
uint256 private constant _AUCTION_POINT_BYTES_SIZE = 5; // _AUCTION_POINT_DELAY_BYTES_SIZE + _AUCTION_POINT_BUMP_BYTES_SIZE;
uint256 private constant _AUCTION_POINT_DELAY_BIT_SHIFT = 240; // 256 - _AUCTION_POINT_DELAY_BYTES_SIZE * 8;
uint256 private constant _AUCTION_POINT_BUMP_BIT_SHIFT = 232; // 256 - _AUCTION_POINT_BUMP_BYTES_SIZE * 8;
uint256 private constant _RESOLVER_TIME_LIMIT_BYTES_SIZE = 4;
uint256 private constant _RESOLVER_ADDRESS_BYTES_SIZE = 20;
uint256 private constant _RESOLVER_BYTES_SIZE = 24; // _RESOLVER_TIME_LIMIT_BYTES_SIZE + _RESOLVER_ADDRESS_BYTES_SIZE;
uint256 private constant _RESOLVER_TIME_LIMIT_BIT_SHIFT = 224; // 256 - _RESOLVER_TIME_LIMIT_BYTES_SIZE * 8;
uint256 private constant _RESOLVER_ADDRESS_BIT_SHIFT = 96; // 256 - _RESOLVER_ADDRESS_BYTES_SIZE * 8;
function takingFee(OrderLib.Order calldata order) internal pure returns (TakingFee.Data ret) {
bytes calldata interactions = order.interactions;
assembly {
let ptr := sub(add(interactions.offset, interactions.length), 1)
if and(_HAS_TAKING_FEE_FLAG, byte(0, calldataload(ptr))) {
ret := calldataload(sub(ptr, _TAKING_FEE_BYTES_SIZE))
}
}
}
function checkResolver(OrderLib.Order calldata order, address resolver) internal view returns (bool valid) {
bytes calldata interactions = order.interactions;
assembly {
let ptr := sub(add(interactions.offset, interactions.length), 1)
let flags := byte(0, calldataload(ptr))
ptr := sub(ptr, _PUBLIC_TIME_LIMIT_BYTES_SIZE)
if and(flags, _HAS_TAKING_FEE_FLAG) {
ptr := sub(ptr, _TAKING_FEE_BYTES_SIZE)
}
let resolversCount := shr(_RESOLVERS_LENGTH_BIT_SHIFT, and(flags, _RESOLVERS_LENGTH_MASK))
// Check public time limit
let publicLimit := shr(_PUBLIC_TIME_LIMIT_BIT_SHIFT, calldataload(ptr))
valid := gt(timestamp(), publicLimit)
// Check resolvers and corresponding time limits
if not(valid) {
for { let end := sub(ptr, mul(_RESOLVER_BYTES_SIZE, resolversCount)) } gt(ptr, end) { } {
ptr := sub(ptr, _RESOLVER_ADDRESS_BYTES_SIZE)
let account := shr(_RESOLVER_ADDRESS_BIT_SHIFT, calldataload(ptr))
ptr := sub(ptr, _RESOLVER_TIME_LIMIT_BYTES_SIZE)
let limit := shr(_RESOLVER_TIME_LIMIT_BIT_SHIFT, calldataload(ptr))
if eq(account, resolver) {
valid := iszero(lt(timestamp(), limit))
break
}
}
}
}
}
function rateBump(OrderLib.Order calldata order) internal view returns (uint256 bump) {
uint256 startBump = order.salt.getInitialRateBump();
uint256 cumulativeTime = order.salt.getStartTime();
uint256 lastTime = cumulativeTime + order.salt.getDuration();
if (block.timestamp <= cumulativeTime) {
return startBump;
} else if (block.timestamp >= lastTime) {
return 0;
}
bytes calldata interactions = order.interactions;
assembly {
function linearInterpolation(t1, t2, v1, v2, t) -> v {
v := div(
add(mul(sub(t, t1), v2), mul(sub(t2, t), v1)),
sub(t2, t1)
)
}
let ptr := sub(add(interactions.offset, interactions.length), 1)
// move ptr to the last point
let pointsCount
{ // stack too deep
let flags := byte(0, calldataload(ptr))
let resolversCount := shr(_RESOLVERS_LENGTH_BIT_SHIFT, and(flags, _RESOLVERS_LENGTH_MASK))
pointsCount := and(flags, _POINTS_LENGTH_MASK)
if and(flags, _HAS_TAKING_FEE_FLAG) {
ptr := sub(ptr, _TAKING_FEE_BYTES_SIZE)
}
ptr := sub(ptr, add(mul(_RESOLVER_BYTES_SIZE, resolversCount), _PUBLIC_TIME_LIMIT_BYTES_SIZE)) // 24 byte for each wl entry + 4 bytes for public time limit
}
// Check points sequentially
let prevCoefficient := startBump
let prevCumulativeTime := cumulativeTime
for { let end := sub(ptr, mul(_AUCTION_POINT_BYTES_SIZE, pointsCount)) } gt(ptr, end) { } {
ptr := sub(ptr, _AUCTION_POINT_BUMP_BYTES_SIZE)
let coefficient := shr(_AUCTION_POINT_BUMP_BIT_SHIFT, calldataload(ptr))
ptr := sub(ptr, _AUCTION_POINT_DELAY_BYTES_SIZE)
let delay := shr(_AUCTION_POINT_DELAY_BIT_SHIFT, calldataload(ptr))
cumulativeTime := add(cumulativeTime, delay)
if gt(cumulativeTime, timestamp()) {
// prevCumulativeTime <passed> time <elapsed> cumulativeTime
// prevCoefficient <passed> X <elapsed> coefficient
bump := linearInterpolation(
prevCumulativeTime,
cumulativeTime,
prevCoefficient,
coefficient,
timestamp()
)
break
}
prevCumulativeTime := cumulativeTime
prevCoefficient := coefficient
}
if iszero(bump) {
bump := linearInterpolation(
prevCumulativeTime,
lastTime,
prevCoefficient,
0,
timestamp()
)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
library TakingFee {
type Data is uint256;
uint256 internal constant _TAKING_FEE_BASE = 1e9;
uint256 private constant _TAKING_FEE_RATIO_OFFSET = 160;
function init(address receiver_, uint256 ratio_) internal pure returns (Data) {
if (ratio_ == 0) {
return Data.wrap(uint160(receiver_));
}
return Data.wrap(uint160(receiver_) | (ratio_ << _TAKING_FEE_RATIO_OFFSET));
}
function enabled(Data self) internal pure returns (bool) {
return ratio(self) != 0;
}
function ratio(Data self) internal pure returns (uint256) {
return uint32(Data.unwrap(self) >> _TAKING_FEE_RATIO_OFFSET);
}
function receiver(Data self) internal pure returns (address) {
return address(uint160(Data.unwrap(self)));
}
}{
"optimizer": {
"enabled": true,
"runs": 1000000
},
"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"},{"internalType":"contract IERC20","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"FailedExternalCall","type":"error"},{"inputs":[],"name":"ForceApproveFailed","type":"error"},{"inputs":[],"name":"IncorrectCalldataParams","type":"error"},{"inputs":[],"name":"NotEnoughCredit","type":"error"},{"inputs":[],"name":"OnlyFeeBankAccess","type":"error"},{"inputs":[],"name":"ResolverIsNotWhitelisted","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"WrongInteractionTarget","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"availableCredit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseAvailableCredit","outputs":[{"internalType":"uint256","name":"allowance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeBank","outputs":[{"internalType":"contract IFeeBank","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"interactiveData","type":"bytes"}],"name":"fillOrderInteraction","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseAvailableCredit","outputs":[{"internalType":"uint256","name":"allowance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"settleOrders","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b50604051620023a0380380620023a0833981016040819052610031916100c1565b803081336040516100419061009b565b6001600160a01b03938416815291831660208301529091166040820152606001604051809103906000f08015801561007d573d6000803e3d6000fd5b506001600160a01b039081166080529290921660a052506100fb9050565b611120806200128083390190565b6001600160a01b03811681146100be57600080fd5b50565b600080604083850312156100d457600080fd5b82516100df816100a9565b60208401519092506100f0816100a9565b809150509250929050565b60805160a0516111436200013d6000396000818161035b015281816106a4015261077f01526000818161010001528181610197015261026901526111436000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806385eda2de1161005057806385eda2de146100e8578063af15d786146100fb578063ccee33d71461014757600080fd5b80630965d04b146100775780633ee5ef1f1461008c5780635886216f146100b2575b600080fd5b61008a610085366004610d52565b61015a565b005b61009f61009a366004610dbd565b61017d565b6040519081526020015b60405180910390f35b61009f6100c0366004610de7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61009f6100f6366004610dbd565b61024f565b6101227f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a9565b61009f610155366004610e09565b6102f1565b60408051600080825260208201909252610179918491849133916106db565b5050565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101ee576040517fa454419900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205461021f8282610ecf565b73ffffffffffffffffffffffffffffffffffffffff90931660009081526020819052604090208390555090919050565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146102c0576040517fa454419900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205461021f8282610ee8565b60008573ffffffffffffffffffffffffffffffffffffffff81163014610343576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103b2576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8284017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081810135918290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40810192918101919060018801908881037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f01907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80810135906298968090610489907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0013582610ecf565b610493908d610efb565b61049d9190610f12565b97506000633b9aca006104bd63ffffffff60808a013560a01c168b610efb565b6104c79190610f12565b905060006104d6866040610ecf565b67ffffffffffffffff8111156104ee576104ee610e71565b6040519080825280601f01601f191660200182016040528015610518576020820181803683370190505b509050602081018688823786018381528a83016020909101527f01000000000000000000000000000000000000000000000000000000000000008c8c60008161056357610563610f4d565b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361064b576105a3602089013589356108a3565b60006105af8587610f7c565b60601c90503660006105c4876014818b610fc4565b915091508273ffffffffffffffffffffffffffffffffffffffff16631944799f6105ef8d6020013590565b8685856040518563ffffffff1660e01b81526004016106119493929190610fee565b600060405180830381600087803b15801561062b57600080fd5b505af115801561063f573d6000803e3d6000fd5b5050505050505061065d565b61065d858560208b01358b35856106db565b81156106885761068873ffffffffffffffffffffffffffffffffffffffff841660808a013584610936565b6106c973ffffffffffffffffffffffffffffffffffffffff84167f00000000000000000000000000000000000000000000000000000000000000008c61099d565b50505050505050505095945050505050565b843585016106e98185610a66565b61071f576040517f4b57606900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061072a82610b37565b905061074766038d7ea4c6800063ffffffff843560901c16610efb565b6107519085610ecf565b9350600061075e83610b70565b90506000845160a06107709190610ecf565b61077b906020610ecf565b90507f00000000000000000000000000000000000000000000000000000000000000006107b1565b8281848460045afa50505050565b60408a013560208101818c0135818d013560601c308114156014831017156107fd577f5b34bf890000000000000000000000000000000000000000000000000000000060005260046000fd5b506040517fe5d7bde60000000000000000000000000000000000000000000000000000000081528c8e600483013785820160048583010152818382010193508a60048501528b60248501526040890135604485015286606485015287608485015289516108718160208d0160a488016107a3565b84810160a40152600081878f016004018183895af1610893573d6000823e3d81fd5b5050505050505050505050505050565b80156101795773ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610909576040517fa7fd379200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff92909216600090815260208190526040902091039055565b610962837fa9059cbb000000000000000000000000000000000000000000000000000000008484610cb5565b610998576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6109c9837f095ea7b3000000000000000000000000000000000000000000000000000000008484610cb5565b610998576109fa837f095ea7b300000000000000000000000000000000000000000000000000000000846000610cb5565b1580610a2f5750610a2d837f095ea7b3000000000000000000000000000000000000000000000000000000008484610cb5565b155b15610998576040517f19be9a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003681610a786101208601866110a8565b91509150600181830103803560001a6004820391506080811615610a9d576020820391505b813560e01c4211945060031c600f16841915610b2d578060180282035b80831115610b2b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88301927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec013560601c833560e01c888203610b24574210159650610b2b9050565b5050610aba565b505b5050505092915050565b60003681610b496101208501856110a8565b91509150600181830103803560001a60801615610b6857602081033593505b505050919050565b600062ffffff823560b081901c82169160e082901c918491610b969160c81c1683610ecf565b9050814211610ba85750909392505050565b804210610bba57506000949350505050565b366000610bcb6101208801886110a8565b915091506001818301036000813560001a6078811660031c6007821692506080821615610bf9576020840393505b6004816018020184039350505086868260050284035b80851115610c95577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8501803560f01c9990990198947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd013560e81c428a1115610c8b57828a03428481038302908c03860201049b5050610c95565b9250889150610c0f565b5089610ca75780870342880383020499505b505050505050505050919050565b60006040518481528360048201528260248201526020600060448360008a5af19150508015610d01573d8015610cf757600160005114601f3d11169150610cff565b6000863b1191505b505b949350505050565b60008083601f840112610d1b57600080fd5b50813567ffffffffffffffff811115610d3357600080fd5b602083019150836020828501011115610d4b57600080fd5b9250929050565b60008060208385031215610d6557600080fd5b823567ffffffffffffffff811115610d7c57600080fd5b610d8885828601610d09565b90969095509350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610db857600080fd5b919050565b60008060408385031215610dd057600080fd5b610dd983610d94565b946020939093013593505050565b600060208284031215610df957600080fd5b610e0282610d94565b9392505050565b600080600080600060808688031215610e2157600080fd5b610e2a86610d94565b94506020860135935060408601359250606086013567ffffffffffffffff811115610e5457600080fd5b610e6088828901610d09565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610ee257610ee2610ea0565b92915050565b81810381811115610ee257610ee2610ea0565b8082028115828204841417610ee257610ee2610ea0565b600082610f48577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015610fbc5780818660140360031b1b83161692505b505092915050565b60008085851115610fd457600080fd5b83861115610fe157600080fd5b5050820193919092039150565b73ffffffffffffffffffffffffffffffffffffffff8516815260006020606081840152855180606085015260005b818110156110385787810183015185820160800152820161101c565b506000608082860101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0915081601f820116840190506080848203016040850152846080820152848660a0830137600060a0868301015260a082601f8701168201019250505095945050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126110dd57600080fd5b83018035915067ffffffffffffffff8211156110f857600080fd5b602001915036819003821315610d4b57600080fdfea26469706673582212209c7fa27ec20c16ed309e2009a17458ca2682f2e05f31b135d716c14e5c5730f464736f6c6343000811003360c06040523480156200001157600080fd5b5060405162001120380380620011208339810160408190526200003491620001ad565b6200003f3362000066565b6001600160a01b0380841660a05282166080526200005d81620000b6565b50505062000201565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b620000c062000139565b6001600160a01b0381166200012b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620001368162000066565b50565b6000546001600160a01b03163314620001955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000122565b565b6001600160a01b03811681146200013657600080fd5b600080600060608486031215620001c357600080fd5b8351620001d08162000197565b6020850151909350620001e38162000197565b6040850151909250620001f68162000197565b809150509250925092565b60805160a051610ecf620002516000396000818161028b015281816103a0015281816105c101526107780152600081816102070152818161047c0152818161068701526106ca0152610ecf6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063715018a611610081578063b6b55f251161005b578063b6b55f2514610185578063bfe9173414610198578063f2fde38b146101ab57600080fd5b8063715018a6146101405780638da5cb5b1461014a57806397a2cb641461017257600080fd5b80632f4f21e2116100b25780632f4f21e21461010757806332d323a51461011a5780635886216f1461012d57600080fd5b8063205c2878146100ce5780632e1a7d4d146100f4575b600080fd5b6100e16100dc366004610b65565b6101be565b6040519081526020015b60405180910390f35b6100e1610102366004610b8f565b6101d3565b6100e1610115366004610b65565b6101df565b6100e1610128366004610bf1565b6101eb565b6100e161013b366004610c4b565b610243565b6101486102f8565b005b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100eb565b6100e1610180366004610c95565b61030c565b6100e1610193366004610b8f565b6104a9565b6100e16101a6366004610d78565b6104b5565b6101486101b9366004610c4b565b6104cd565b60006101ca8383610589565b90505b92915050565b60006101cd3383610589565b60006101ca83836106ae565b600061022e73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001684846107e5565b61023885856106ae565b90505b949350505050565b6040517f5886216f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690635886216f90602401602060405180830381865afa1580156102d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101cd9190610dc4565b610300610801565b61030a6000610882565b565b6000610316610801565b815160005b8181101561046157600084828151811061033757610337610ddd565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8082166000818152600190945260408085205490517f5886216f00000000000000000000000000000000000000000000000000000000815260048101929092529294509192917f000000000000000000000000000000000000000000000000000000000000000090911690635886216f90602401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d9190610dc4565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260016020526040902081905590506104418183610e3b565b61044b9087610e4e565b95505050508061045a90610e61565b905061031b565b506104a373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633846108f7565b50919050565b60006101cd33836106ae565b60006104c3338585856101eb565b90505b9392505050565b6104d5610801565b73ffffffffffffffffffffffffffffffffffffffff811661057d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61058681610882565b50565b6040517f85eda2de000000000000000000000000000000000000000000000000000000008152336004820152602481018290526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906385eda2de906044016020604051808303816000875af115801561061f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106439190610dc4565b33600090815260016020526040812080549293508492909190610667908490610e3b565b909155506101cd905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001684846108f7565b60006106f273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333085610959565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081208054849290610727908490610e4e565b90915550506040517f3ee5ef1f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f00000000000000000000000000000000000000000000000000000000000000001690633ee5ef1f906044016020604051808303816000875af11580156107c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101ca9190610dc4565b6107f08383836109f6565b6107fc576107fc610a9c565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461030a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610574565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610923837fa9059cbb000000000000000000000000000000000000000000000000000000008484610aa8565b6107fc576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af191505080156109b7573d80156109ad57600160005114601f3d111691506109b5565b6000873b1191505b505b806109ee576040517ff405907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b600060e0829003610a3457610a2d847fd505accf000000000000000000000000000000000000000000000000000000008585610afb565b90506104c6565b610100829003610a6a57610a2d847f8fcbaf0c000000000000000000000000000000000000000000000000000000008585610afb565b6040517f6827585700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040513d6000823e3d81fd5b60006040518481528360048201528260248201526020600060448360008a5af1915050801561023b573d8015610aea57600160005114601f3d11169150610af2565b6000863b1191505b50949350505050565b6000816004016040518581528385600483013760206000838360008b5af192505050801561023b573d8015610aea57600160005114601f3d11169150610af2565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b6057600080fd5b919050565b60008060408385031215610b7857600080fd5b610b8183610b3c565b946020939093013593505050565b600060208284031215610ba157600080fd5b5035919050565b60008083601f840112610bba57600080fd5b50813567ffffffffffffffff811115610bd257600080fd5b602083019150836020828501011115610bea57600080fd5b9250929050565b60008060008060608587031215610c0757600080fd5b610c1085610b3c565b935060208501359250604085013567ffffffffffffffff811115610c3357600080fd5b610c3f87828801610ba8565b95989497509550505050565b600060208284031215610c5d57600080fd5b6101ca82610b3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215610ca857600080fd5b823567ffffffffffffffff80821115610cc057600080fd5b818501915085601f830112610cd457600080fd5b813581811115610ce657610ce6610c66565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108582111715610d2957610d29610c66565b604052918252848201925083810185019188831115610d4757600080fd5b938501935b82851015610d6c57610d5d85610b3c565b84529385019392850192610d4c565b98975050505050505050565b600080600060408486031215610d8d57600080fd5b83359250602084013567ffffffffffffffff811115610dab57600080fd5b610db786828701610ba8565b9497909650939450505050565b600060208284031215610dd657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156101cd576101cd610e0c565b808201808211156101cd576101cd610e0c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610e9257610e92610e0c565b506001019056fea26469706673582212203c4030d8e4fd032251f47f19b257241211e815812cd7d45d8d965652ddf2470e64736f6c634300081100330000000000000000000000001111111254eeb25477b68fb85ed929f73a960582000000000000000000000000111111111117dc0aa78b770fa6a738034120c302
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100725760003560e01c806385eda2de1161005057806385eda2de146100e8578063af15d786146100fb578063ccee33d71461014757600080fd5b80630965d04b146100775780633ee5ef1f1461008c5780635886216f146100b2575b600080fd5b61008a610085366004610d52565b61015a565b005b61009f61009a366004610dbd565b61017d565b6040519081526020015b60405180910390f35b61009f6100c0366004610de7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61009f6100f6366004610dbd565b61024f565b6101227f000000000000000000000000a0844e046a5b7db55bb8dcdffbf0bbf9c6dc654681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a9565b61009f610155366004610e09565b6102f1565b60408051600080825260208201909252610179918491849133916106db565b5050565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0844e046a5b7db55bb8dcdffbf0bbf9c6dc654616146101ee576040517fa454419900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205461021f8282610ecf565b73ffffffffffffffffffffffffffffffffffffffff90931660009081526020819052604090208390555090919050565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0844e046a5b7db55bb8dcdffbf0bbf9c6dc654616146102c0576040517fa454419900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205461021f8282610ee8565b60008573ffffffffffffffffffffffffffffffffffffffff81163014610343576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001111111254eeb25477b68fb85ed929f73a96058216146103b2576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8284017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081810135918290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40810192918101919060018801908881037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f01907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80810135906298968090610489907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0013582610ecf565b610493908d610efb565b61049d9190610f12565b97506000633b9aca006104bd63ffffffff60808a013560a01c168b610efb565b6104c79190610f12565b905060006104d6866040610ecf565b67ffffffffffffffff8111156104ee576104ee610e71565b6040519080825280601f01601f191660200182016040528015610518576020820181803683370190505b509050602081018688823786018381528a83016020909101527f01000000000000000000000000000000000000000000000000000000000000008c8c60008161056357610563610f4d565b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361064b576105a3602089013589356108a3565b60006105af8587610f7c565b60601c90503660006105c4876014818b610fc4565b915091508273ffffffffffffffffffffffffffffffffffffffff16631944799f6105ef8d6020013590565b8685856040518563ffffffff1660e01b81526004016106119493929190610fee565b600060405180830381600087803b15801561062b57600080fd5b505af115801561063f573d6000803e3d6000fd5b5050505050505061065d565b61065d858560208b01358b35856106db565b81156106885761068873ffffffffffffffffffffffffffffffffffffffff841660808a013584610936565b6106c973ffffffffffffffffffffffffffffffffffffffff84167f0000000000000000000000001111111254eeb25477b68fb85ed929f73a9605828c61099d565b50505050505050505095945050505050565b843585016106e98185610a66565b61071f576040517f4b57606900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061072a82610b37565b905061074766038d7ea4c6800063ffffffff843560901c16610efb565b6107519085610ecf565b9350600061075e83610b70565b90506000845160a06107709190610ecf565b61077b906020610ecf565b90507f0000000000000000000000001111111254eeb25477b68fb85ed929f73a9605826107b1565b8281848460045afa50505050565b60408a013560208101818c0135818d013560601c308114156014831017156107fd577f5b34bf890000000000000000000000000000000000000000000000000000000060005260046000fd5b506040517fe5d7bde60000000000000000000000000000000000000000000000000000000081528c8e600483013785820160048583010152818382010193508a60048501528b60248501526040890135604485015286606485015287608485015289516108718160208d0160a488016107a3565b84810160a40152600081878f016004018183895af1610893573d6000823e3d81fd5b5050505050505050505050505050565b80156101795773ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610909576040517fa7fd379200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff92909216600090815260208190526040902091039055565b610962837fa9059cbb000000000000000000000000000000000000000000000000000000008484610cb5565b610998576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6109c9837f095ea7b3000000000000000000000000000000000000000000000000000000008484610cb5565b610998576109fa837f095ea7b300000000000000000000000000000000000000000000000000000000846000610cb5565b1580610a2f5750610a2d837f095ea7b3000000000000000000000000000000000000000000000000000000008484610cb5565b155b15610998576040517f19be9a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003681610a786101208601866110a8565b91509150600181830103803560001a6004820391506080811615610a9d576020820391505b813560e01c4211945060031c600f16841915610b2d578060180282035b80831115610b2b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe88301927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec013560601c833560e01c888203610b24574210159650610b2b9050565b5050610aba565b505b5050505092915050565b60003681610b496101208501856110a8565b91509150600181830103803560001a60801615610b6857602081033593505b505050919050565b600062ffffff823560b081901c82169160e082901c918491610b969160c81c1683610ecf565b9050814211610ba85750909392505050565b804210610bba57506000949350505050565b366000610bcb6101208801886110a8565b915091506001818301036000813560001a6078811660031c6007821692506080821615610bf9576020840393505b6004816018020184039350505086868260050284035b80851115610c95577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8501803560f01c9990990198947ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd013560e81c428a1115610c8b57828a03428481038302908c03860201049b5050610c95565b9250889150610c0f565b5089610ca75780870342880383020499505b505050505050505050919050565b60006040518481528360048201528260248201526020600060448360008a5af19150508015610d01573d8015610cf757600160005114601f3d11169150610cff565b6000863b1191505b505b949350505050565b60008083601f840112610d1b57600080fd5b50813567ffffffffffffffff811115610d3357600080fd5b602083019150836020828501011115610d4b57600080fd5b9250929050565b60008060208385031215610d6557600080fd5b823567ffffffffffffffff811115610d7c57600080fd5b610d8885828601610d09565b90969095509350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610db857600080fd5b919050565b60008060408385031215610dd057600080fd5b610dd983610d94565b946020939093013593505050565b600060208284031215610df957600080fd5b610e0282610d94565b9392505050565b600080600080600060808688031215610e2157600080fd5b610e2a86610d94565b94506020860135935060408601359250606086013567ffffffffffffffff811115610e5457600080fd5b610e6088828901610d09565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610ee257610ee2610ea0565b92915050565b81810381811115610ee257610ee2610ea0565b8082028115828204841417610ee257610ee2610ea0565b600082610f48577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008135818116916014851015610fbc5780818660140360031b1b83161692505b505092915050565b60008085851115610fd457600080fd5b83861115610fe157600080fd5b5050820193919092039150565b73ffffffffffffffffffffffffffffffffffffffff8516815260006020606081840152855180606085015260005b818110156110385787810183015185820160800152820161101c565b506000608082860101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0915081601f820116840190506080848203016040850152846080820152848660a0830137600060a0868301015260a082601f8701168201019250505095945050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126110dd57600080fd5b83018035915067ffffffffffffffff8211156110f857600080fd5b602001915036819003821315610d4b57600080fdfea26469706673582212209c7fa27ec20c16ed309e2009a17458ca2682f2e05f31b135d716c14e5c5730f464736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582000000000000000000000000111111111117dc0aa78b770fa6a738034120c302
-----Decoded View---------------
Arg [0] : limitOrderProtocol (address): 0x1111111254EEB25477B68fb85Ed929f73A960582
Arg [1] : token (address): 0x111111111117dC0aa78b770fA6A738034120C302
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582
Arg [1] : 000000000000000000000000111111111117dc0aa78b770fa6a738034120c302
Loading...
Loading
Loading...
Loading
OVERVIEW
The DeFi ecosystem building financial freedom for everyone. 1inch products make it easier for users and builders to trade, hold and track digital assets - and 1inch protocols and APIs provide core infrastructure for the DeFi industry and beyond.Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 45.23% | $3,366.28 | 0.00425174 | $14.31 | |
| ETH | 14.23% | $1 | 4.498 | $4.5 | |
| ETH | 5.86% | $0.173163 | 10.711 | $1.85 | |
| ETH | 4.45% | $0.108372 | 12.9942 | $1.41 | |
| ETH | 2.03% | $18.45 | 0.0348 | $0.6428 | |
| ETH | 1.59% | <$0.000001 | 186,738,158.7996 | $0.5026 | |
| ETH | 1.18% | $0.000062 | 6,029.7524 | $0.3722 | |
| ETH | 1.10% | $0.003166 | 110.3115 | $0.3492 | |
| ETH | 1.08% | $3,319.7 | 0.00010248 | $0.3402 | |
| ETH | 0.96% | $0.000084 | 3,609.526 | $0.3043 | |
| ETH | 0.86% | $0.057002 | 4.7932 | $0.2732 | |
| ETH | 0.83% | $1.73 | 0.1512 | $0.2615 | |
| ETH | 0.68% | $0.000146 | 1,479.428 | $0.2153 | |
| ETH | 0.66% | $136.06 | 0.00154688 | $0.2104 | |
| ETH | 0.63% | $0.00549 | 36.4747 | $0.2002 | |
| ETH | 0.61% | $0.410716 | 0.4672 | $0.1918 | |
| ETH | 0.55% | $9.23 | 0.0188 | $0.1733 | |
| ETH | 0.48% | <$0.000001 | 184,848,164.7694 | $0.1529 | |
| ETH | 0.42% | $0.004234 | 31.7236 | $0.1343 | |
| ETH | 0.41% | $1,791.75 | 0.00007324 | $0.1312 | |
| ETH | 0.36% | <$0.000001 | 767,961.7474 | $0.1144 | |
| ETH | 0.35% | $3.83 | 0.0289 | $0.1105 | |
| ETH | 0.34% | <$0.000001 | 5,717,176.0041 | $0.1066 | |
| BASE | 10.06% | $0.019895 | 160 | $3.18 | |
| BASE | 0.48% | <$0.000001 | 11,111,111 | $0.1522 | |
| BERA | 4.57% | $0.866328 | 1.6684 | $1.45 | |
| POL | <0.01% | $0.123928 | 0.0043 | $0.000533 |
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.