Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 40,881 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Increase Nonce | 21163481 | 475 days ago | IN | 0 ETH | 0.00097677 | ||||
| Increase Nonce | 19887990 | 653 days ago | IN | 0 ETH | 0.00017644 | ||||
| Increase Nonce | 19614474 | 692 days ago | IN | 0 ETH | 0.00097716 | ||||
| Increase Nonce | 19498462 | 708 days ago | IN | 0 ETH | 0.00094213 | ||||
| Cancel Order | 19380456 | 724 days ago | IN | 0 ETH | 0.00346042 | ||||
| Increase Nonce | 19332334 | 731 days ago | IN | 0 ETH | 0.00292462 | ||||
| Cancel Order | 19275768 | 739 days ago | IN | 0 ETH | 0.00177482 | ||||
| Increase Nonce | 19164199 | 755 days ago | IN | 0 ETH | 0.00101118 | ||||
| Increase Nonce | 19045701 | 771 days ago | IN | 0 ETH | 0.00069234 | ||||
| Increase Nonce | 18991419 | 779 days ago | IN | 0 ETH | 0.00089557 | ||||
| Cancel Order | 18962592 | 783 days ago | IN | 0 ETH | 0.00127045 | ||||
| Cancel Order | 18962263 | 783 days ago | IN | 0 ETH | 0.00122638 | ||||
| Cancel Order | 18859863 | 797 days ago | IN | 0 ETH | 0.00090981 | ||||
| Cancel Order | 18828265 | 802 days ago | IN | 0 ETH | 0.00431852 | ||||
| Cancel Order | 18828263 | 802 days ago | IN | 0 ETH | 0.00416908 | ||||
| Cancel Order | 18803030 | 805 days ago | IN | 0 ETH | 0.00188852 | ||||
| Cancel Order | 18802899 | 805 days ago | IN | 0 ETH | 0.00186743 | ||||
| Fill Order | 18704941 | 819 days ago | IN | 0 ETH | 0.02334475 | ||||
| Increase Nonce | 18690220 | 821 days ago | IN | 0 ETH | 0.00155219 | ||||
| Fill Order | 18655209 | 826 days ago | IN | 0 ETH | 0.01753347 | ||||
| Fill Order | 18604697 | 833 days ago | IN | 0 ETH | 0.01298971 | ||||
| Increase Nonce | 18592598 | 835 days ago | IN | 0 ETH | 0.00131159 | ||||
| Fill Order | 18554991 | 840 days ago | IN | 0 ETH | 0.01952589 | ||||
| Increase Nonce | 18543563 | 842 days ago | IN | 0 ETH | 0.0017649 | ||||
| Cancel Order | 18543230 | 842 days ago | IN | 0 ETH | 0.00297353 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LimitOrderProtocol
Compiler Version
v0.8.10+commit.fc410830
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.10;
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "./OrderMixin.sol";
import "./OrderRFQMixin.sol";
/// @title 1inch Limit Order Protocol v2
contract LimitOrderProtocol is
EIP712("1inch Limit Order Protocol", "2"),
OrderMixin,
OrderRFQMixin
{
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns(bytes32) {
return _domainSeparatorV4();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/cryptography/draft-EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./helpers/AmountCalculator.sol";
import "./helpers/ChainlinkCalculator.sol";
import "./helpers/NonceManager.sol";
import "./helpers/PredicateHelper.sol";
import "./interfaces/InteractiveNotificationReceiver.sol";
import "./libraries/ArgumentsDecoder.sol";
import "./libraries/Permitable.sol";
/// @title Regular Limit Order mixin
abstract contract OrderMixin is
EIP712,
AmountCalculator,
ChainlinkCalculator,
NonceManager,
PredicateHelper,
Permitable
{
using Address for address;
using ArgumentsDecoder for bytes;
/// @notice Emitted every time order gets filled, including partial fills
event OrderFilled(
address indexed maker,
bytes32 orderHash,
uint256 remaining
);
/// @notice Emitted when order gets cancelled
event OrderCanceled(
address indexed maker,
bytes32 orderHash,
uint256 remainingRaw
);
// Fixed-size order part with core information
struct StaticOrder {
uint256 salt;
address makerAsset;
address takerAsset;
address maker;
address receiver;
address allowedSender; // equals to Zero address on public orders
uint256 makingAmount;
uint256 takingAmount;
}
// `StaticOrder` extension including variable-sized additional order meta information
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;
bytes makerAssetData;
bytes takerAssetData;
bytes getMakerAmount; // this.staticcall(abi.encodePacked(bytes, swapTakerAmount)) => (swapMakerAmount)
bytes getTakerAmount; // 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 interaction;
}
bytes32 constant public LIMIT_ORDER_TYPEHASH = keccak256(
"Order(uint256 salt,address makerAsset,address takerAsset,address maker,address receiver,address allowedSender,uint256 makingAmount,uint256 takingAmount,bytes makerAssetData,bytes takerAssetData,bytes getMakerAmount,bytes getTakerAmount,bytes predicate,bytes permit,bytes interaction)"
);
uint256 constant private _ORDER_DOES_NOT_EXIST = 0;
uint256 constant private _ORDER_FILLED = 1;
/// @notice Stores unfilled amounts for each order plus one.
/// Therefore 0 means order doesn't exist and 1 means order was filled
mapping(bytes32 => uint256) private _remaining;
/// @notice Returns unfilled amount for order. Throws if order does not exist
function remaining(bytes32 orderHash) external view returns(uint256) {
uint256 amount = _remaining[orderHash];
require(amount != _ORDER_DOES_NOT_EXIST, "LOP: Unknown order");
unchecked { amount -= 1; }
return amount;
}
/// @notice Returns unfilled amount for order
/// @return Result Unfilled amount of order plus one if order exists. Otherwise 0
function remainingRaw(bytes32 orderHash) external view returns(uint256) {
return _remaining[orderHash];
}
/// @notice Same as `remainingRaw` but for multiple orders
function remainingsRaw(bytes32[] memory orderHashes) external view returns(uint256[] memory) {
uint256[] memory results = new uint256[](orderHashes.length);
for (uint256 i = 0; i < orderHashes.length; i++) {
results[i] = _remaining[orderHashes[i]];
}
return results;
}
/**
* @notice Calls every target with corresponding data. Then reverts with CALL_RESULTS_0101011 where zeroes and ones
* denote failure or success of the corresponding call
* @param targets Array of addresses that will be called
* @param data Array of data that will be passed to each call
*/
function simulateCalls(address[] calldata targets, bytes[] calldata data) external {
require(targets.length == data.length, "LOP: array size mismatch");
bytes memory reason = new bytes(targets.length);
for (uint256 i = 0; i < targets.length; i++) {
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory result) = targets[i].call(data[i]);
if (success && result.length > 0) {
success = result.length == 32 && result.decodeBool();
}
reason[i] = success ? bytes1("1") : bytes1("0");
}
// Always revert and provide per call results
revert(string(abi.encodePacked("CALL_RESULTS_", reason)));
}
/// @notice Cancels order by setting remaining amount to zero
function cancelOrder(Order memory order) external {
require(order.maker == msg.sender, "LOP: Access denied");
bytes32 orderHash = hashOrder(order);
uint256 orderRemaining = _remaining[orderHash];
require(orderRemaining != _ORDER_FILLED, "LOP: already filled");
emit OrderCanceled(msg.sender, orderHash, orderRemaining);
_remaining[orderHash] = _ORDER_FILLED;
}
/// @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 makingAmount Making amount
/// @param takingAmount Taking amount
/// @param thresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount
function fillOrder(
Order memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount,
uint256 thresholdAmount
) external returns(uint256 /* actualMakingAmount */, uint256 /* actualTakingAmount */) {
return fillOrderTo(order, signature, makingAmount, takingAmount, thresholdAmount, msg.sender);
}
/// @notice Same as `fillOrder` 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`
/// @param order Order quote to fill
/// @param signature Signature to confirm quote ownership
/// @param makingAmount Making amount
/// @param takingAmount Taking amount
/// @param thresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount
/// @param target Address that will receive swap funds
/// @param permit Should consist of abiencoded token address and encoded `IERC20Permit.permit` call.
/// @dev See tests for examples
function fillOrderToWithPermit(
Order memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount,
uint256 thresholdAmount,
address target,
bytes calldata permit
) external returns(uint256 /* actualMakingAmount */, uint256 /* actualTakingAmount */) {
require(permit.length >= 20, "LOP: permit length too low");
(address token, bytes calldata permitData) = permit.decodeTargetAndData();
_permit(token, permitData);
return fillOrderTo(order, signature, makingAmount, takingAmount, thresholdAmount, target);
}
/// @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 makingAmount Making amount
/// @param takingAmount Taking amount
/// @param thresholdAmount Specifies maximum allowed takingAmount when takingAmount is zero, otherwise specifies minimum allowed makingAmount
/// @param target Address that will receive swap funds
function fillOrderTo(
Order memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount,
uint256 thresholdAmount,
address target
) public returns(uint256 /* actualMakingAmount */, uint256 /* actualTakingAmount */) {
require(target != address(0), "LOP: zero target is forbidden");
bytes32 orderHash = hashOrder(order);
{ // Stack too deep
uint256 remainingMakerAmount = _remaining[orderHash];
require(remainingMakerAmount != _ORDER_FILLED, "LOP: remaining amount is 0");
require(order.allowedSender == address(0) || order.allowedSender == msg.sender, "LOP: private order");
if (remainingMakerAmount == _ORDER_DOES_NOT_EXIST) {
// First fill: validate order and permit maker asset
require(SignatureChecker.isValidSignatureNow(order.maker, orderHash, signature), "LOP: bad signature");
remainingMakerAmount = order.makingAmount;
if (order.permit.length >= 20) {
// proceed only if permit length is enough to store address
(address token, bytes memory permit) = order.permit.decodeTargetAndCalldata();
_permitMemory(token, permit);
require(_remaining[orderHash] == _ORDER_DOES_NOT_EXIST, "LOP: reentrancy detected");
}
} else {
unchecked { remainingMakerAmount -= 1; }
}
// Check if order is valid
if (order.predicate.length > 0) {
require(checkPredicate(order), "LOP: predicate returned false");
}
// Compute maker and taker assets amount
if ((takingAmount == 0) == (makingAmount == 0)) {
revert("LOP: only one amount should be 0");
} else if (takingAmount == 0) {
uint256 requestedMakingAmount = makingAmount;
if (makingAmount > remainingMakerAmount) {
makingAmount = remainingMakerAmount;
}
takingAmount = _callGetter(order.getTakerAmount, order.makingAmount, makingAmount, order.takingAmount);
// check that actual rate is not worse than what was expected
// takingAmount / makingAmount <= thresholdAmount / requestedMakingAmount
require(takingAmount * requestedMakingAmount <= thresholdAmount * makingAmount, "LOP: taking amount too high");
} else {
uint256 requestedTakingAmount = takingAmount;
makingAmount = _callGetter(order.getMakerAmount, order.takingAmount, takingAmount, order.makingAmount);
if (makingAmount > remainingMakerAmount) {
makingAmount = remainingMakerAmount;
takingAmount = _callGetter(order.getTakerAmount, order.makingAmount, makingAmount, order.takingAmount);
}
// check that actual rate is not worse than what was expected
// makingAmount / takingAmount >= thresholdAmount / requestedTakingAmount
require(makingAmount * requestedTakingAmount >= thresholdAmount * takingAmount, "LOP: making amount too low");
}
require(makingAmount > 0 && takingAmount > 0, "LOP: can't swap 0 amount");
// Update remaining amount in storage
unchecked {
remainingMakerAmount = remainingMakerAmount - makingAmount;
_remaining[orderHash] = remainingMakerAmount + 1;
}
emit OrderFilled(msg.sender, orderHash, remainingMakerAmount);
}
// Taker => Maker
_makeCall(
order.takerAsset,
abi.encodePacked(
IERC20.transferFrom.selector,
uint256(uint160(msg.sender)),
uint256(uint160(order.receiver == address(0) ? order.maker : order.receiver)),
takingAmount,
order.takerAssetData
)
);
// Maker can handle funds interactively
if (order.interaction.length >= 20) {
// proceed only if interaction length is enough to store address
(address interactionTarget, bytes memory interactionData) = order.interaction.decodeTargetAndCalldata();
InteractiveNotificationReceiver(interactionTarget).notifyFillOrder(
msg.sender, order.makerAsset, order.takerAsset, makingAmount, takingAmount, interactionData
);
}
// Maker => Taker
_makeCall(
order.makerAsset,
abi.encodePacked(
IERC20.transferFrom.selector,
uint256(uint160(order.maker)),
uint256(uint160(target)),
makingAmount,
order.makerAssetData
)
);
return (makingAmount, takingAmount);
}
/// @notice Checks order predicate
function checkPredicate(Order memory order) public view returns(bool) {
bytes memory result = address(this).functionStaticCall(order.predicate, "LOP: predicate call failed");
require(result.length == 32, "LOP: invalid predicate return");
return result.decodeBool();
}
function hashOrder(Order memory order) public view returns(bytes32) {
StaticOrder memory staticOrder;
assembly { // solhint-disable-line no-inline-assembly
staticOrder := order
}
return _hashTypedDataV4(
keccak256(
abi.encode(
LIMIT_ORDER_TYPEHASH,
staticOrder,
keccak256(order.makerAssetData),
keccak256(order.takerAssetData),
keccak256(order.getMakerAmount),
keccak256(order.getTakerAmount),
keccak256(order.predicate),
keccak256(order.permit),
keccak256(order.interaction)
)
)
);
}
function _makeCall(address asset, bytes memory assetData) private {
bytes memory result = asset.functionCall(assetData, "LOP: asset.call failed");
if (result.length > 0) {
require(result.length == 32 && result.decodeBool(), "LOP: asset.call bad result");
}
}
function _callGetter(bytes memory getter, uint256 orderExpectedAmount, uint256 amount, uint256 orderResultAmount) private view returns(uint256) {
if (getter.length == 0) {
// On empty getter calldata only exact amount is allowed
require(amount == orderExpectedAmount, "LOP: wrong amount");
return orderResultAmount;
} else {
bytes memory result = address(this).functionStaticCall(abi.encodePacked(getter, amount), "LOP: getAmount call failed");
require(result.length == 32, "LOP: invalid getAmount return");
return result.decodeUint256();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./helpers/AmountCalculator.sol";
import "./libraries/Permitable.sol";
/// @title RFQ Limit Order mixin
abstract contract OrderRFQMixin is EIP712, AmountCalculator, Permitable {
using SafeERC20 for IERC20;
/// @notice Emitted when RFQ gets filled
event OrderFilledRFQ(
bytes32 orderHash,
uint256 makingAmount
);
struct OrderRFQ {
uint256 info; // lowest 64 bits is the order id, next 64 bits is the expiration timestamp
IERC20 makerAsset;
IERC20 takerAsset;
address maker;
address allowedSender; // equals to Zero address on public orders
uint256 makingAmount;
uint256 takingAmount;
}
bytes32 constant public LIMIT_ORDER_RFQ_TYPEHASH = keccak256(
"OrderRFQ(uint256 info,address makerAsset,address takerAsset,address maker,address allowedSender,uint256 makingAmount,uint256 takingAmount)"
);
mapping(address => mapping(uint256 => uint256)) private _invalidator;
/// @notice Returns bitmask for double-spend invalidators based on lowest byte of order.info and filled quotes
/// @return Result Each bit represents whether corresponding was already invalidated
function invalidatorForOrderRFQ(address maker, uint256 slot) external view returns(uint256) {
return _invalidator[maker][slot];
}
/// @notice Cancels order's quote
function cancelOrderRFQ(uint256 orderInfo) external {
_invalidateOrder(msg.sender, orderInfo);
}
/// @notice Fills order's quote, fully or partially (whichever is possible)
/// @param order Order quote to fill
/// @param signature Signature to confirm quote ownership
/// @param makingAmount Making amount
/// @param takingAmount Taking amount
function fillOrderRFQ(
OrderRFQ memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount
) external returns(uint256, uint256) {
return fillOrderRFQTo(order, signature, makingAmount, takingAmount, msg.sender);
}
/// @notice Fills Same as `fillOrderRFQ` 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`
/// @param order Order quote to fill
/// @param signature Signature to confirm quote ownership
/// @param makingAmount Making amount
/// @param takingAmount Taking amount
/// @param target Address that will receive swap funds
/// @param permit Should consist of abiencoded token address and encoded `IERC20Permit.permit` call.
/// @dev See tests for examples
function fillOrderRFQToWithPermit(
OrderRFQ memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount,
address target,
bytes calldata permit
) external returns(uint256, uint256) {
_permit(address(order.takerAsset), permit);
return fillOrderRFQTo(order, signature, makingAmount, takingAmount, target);
}
/// @notice Same as `fillOrderRFQ` but allows to specify funds destination instead of `msg.sender`
/// @param order Order quote to fill
/// @param signature Signature to confirm quote ownership
/// @param makingAmount Making amount
/// @param takingAmount Taking amount
/// @param target Address that will receive swap funds
function fillOrderRFQTo(
OrderRFQ memory order,
bytes calldata signature,
uint256 makingAmount,
uint256 takingAmount,
address target
) public returns(uint256, uint256) {
require(target != address(0), "LOP: zero target is forbidden");
address maker = order.maker;
// Validate order
require(order.allowedSender == address(0) || order.allowedSender == msg.sender, "LOP: private order");
bytes32 orderHash = _hashTypedDataV4(keccak256(abi.encode(LIMIT_ORDER_RFQ_TYPEHASH, order)));
require(SignatureChecker.isValidSignatureNow(maker, orderHash, signature), "LOP: bad signature");
{ // Stack too deep
uint256 info = order.info;
// Check time expiration
uint256 expiration = uint128(info) >> 64;
require(expiration == 0 || block.timestamp <= expiration, "LOP: order expired"); // solhint-disable-line not-rely-on-time
_invalidateOrder(maker, info);
}
{ // stack too deep
uint256 orderMakingAmount = order.makingAmount;
uint256 orderTakingAmount = order.takingAmount;
// Compute partial fill if needed
if (takingAmount == 0 && makingAmount == 0) {
// Two zeros means whole order
makingAmount = orderMakingAmount;
takingAmount = orderTakingAmount;
}
else if (takingAmount == 0) {
require(makingAmount <= orderMakingAmount, "LOP: making amount exceeded");
takingAmount = getTakerAmount(orderMakingAmount, orderTakingAmount, makingAmount);
}
else if (makingAmount == 0) {
require(takingAmount <= orderTakingAmount, "LOP: taking amount exceeded");
makingAmount = getMakerAmount(orderMakingAmount, orderTakingAmount, takingAmount);
}
else {
revert("LOP: both amounts are non-zero");
}
}
require(makingAmount > 0 && takingAmount > 0, "LOP: can't swap 0 amount");
// Maker => Taker, Taker => Maker
order.makerAsset.safeTransferFrom(maker, target, makingAmount);
order.takerAsset.safeTransferFrom(msg.sender, maker, takingAmount);
emit OrderFilledRFQ(orderHash, makingAmount);
return (makingAmount, takingAmount);
}
function _invalidateOrder(address maker, uint256 orderInfo) private {
uint256 invalidatorSlot = uint64(orderInfo) >> 8;
uint256 invalidatorBit = 1 << uint8(orderInfo);
mapping(uint256 => uint256) storage invalidatorStorage = _invalidator[maker];
uint256 invalidator = invalidatorStorage[invalidatorSlot];
require(invalidator & invalidatorBit == 0, "LOP: invalidated order");
invalidatorStorage[invalidatorSlot] = invalidator | invalidatorBit;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s;
uint8 v;
assembly {
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
v := add(shr(255, vs), 27)
}
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// 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.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
import "../Address.sol";
import "../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper: Provide a single mechanism to verify both private-key (EOA) ECDSA signature and
* ERC1271 contract signatures. Using this instead of ECDSA.recover in your contract will make them compatible with
* smart contract wallets such as Argent and Gnosis.
*
* Note: unlike ECDSA signatures, contract signature's are revocable, and the outcome of this function can thus change
* through time. It could return true at block N and false at block N+1 (or the opposite).
*
* _Available since v4.1._
*/
library SignatureChecker {
function isValidSignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
if (error == ECDSA.RecoverError.NoError && recovered == signer) {
return true;
}
(bool success, bytes memory result) = signer.staticcall(
abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
);
return (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
import "@openzeppelin/contracts/utils/Address.sol";
/// @title A helper contract for calculations related to order amounts
contract AmountCalculator {
using Address for address;
/// @notice Calculates maker amount
/// @return Result Floored maker amount
function getMakerAmount(uint256 orderMakerAmount, uint256 orderTakerAmount, uint256 swapTakerAmount) public pure returns(uint256) {
return swapTakerAmount * orderMakerAmount / orderTakerAmount;
}
/// @notice Calculates taker amount
/// @return Result Ceiled taker amount
function getTakerAmount(uint256 orderMakerAmount, uint256 orderTakerAmount, uint256 swapMakerAmount) public pure returns(uint256) {
return (swapMakerAmount * orderTakerAmount + orderMakerAmount - 1) / orderMakerAmount;
}
/// @notice Performs an arbitrary call to target with data
/// @return Result Bytes transmuted to uint256
function arbitraryStaticCall(address target, bytes memory data) external view returns(uint256) {
(bytes memory result) = target.functionStaticCall(data, "AC: arbitraryStaticCall");
return abi.decode(result, (uint256));
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
/// @title A helper contract for interactions with https://docs.chain.link
contract ChainlinkCalculator {
using SafeCast for int256;
uint256 private constant _SPREAD_DENOMINATOR = 1e9;
uint256 private constant _ORACLE_EXPIRATION_TIME = 30 minutes;
uint256 private constant _INVERSE_MASK = 1 << 255;
/// @notice Calculates price of token relative to oracle unit (ETH or USD)
/// @param inverseAndSpread concatenated inverse flag and spread.
/// Lowest 254 bits specify spread amount. Spread is scaled by 1e9, i.e. 101% = 1.01e9, 99% = 0.99e9.
/// Highest bit is set when oracle price should be inverted,
/// e.g. for DAI-ETH oracle, inverse=false means that we request DAI price in ETH
/// and inverse=true means that we request ETH price in DAI
/// @return Amount * spread * oracle price
function singlePrice(AggregatorV3Interface oracle, uint256 inverseAndSpread, uint256 amount) external view returns(uint256) {
(, int256 latestAnswer,, uint256 latestTimestamp,) = oracle.latestRoundData();
// solhint-disable-next-line not-rely-on-time
require(latestTimestamp + _ORACLE_EXPIRATION_TIME > block.timestamp, "CC: stale data");
bool inverse = inverseAndSpread & _INVERSE_MASK > 0;
uint256 spread = inverseAndSpread & (~_INVERSE_MASK);
if (inverse) {
return amount * spread * (10 ** oracle.decimals()) / latestAnswer.toUint256() / _SPREAD_DENOMINATOR;
} else {
return amount * spread * latestAnswer.toUint256() / (10 ** oracle.decimals()) / _SPREAD_DENOMINATOR;
}
}
/// @notice Calculates price of token A relative to token B. Note that order is important
/// @return Result Token A relative price times amount
function doublePrice(AggregatorV3Interface oracle1, AggregatorV3Interface oracle2, uint256 spread, uint256 amount) external view returns(uint256) {
require(oracle1.decimals() == oracle2.decimals(), "CC: oracle decimals don't match");
(, int256 latestAnswer1,, uint256 latestTimestamp1,) = oracle1.latestRoundData();
(, int256 latestAnswer2,, uint256 latestTimestamp2,) = oracle2.latestRoundData();
// solhint-disable-next-line not-rely-on-time
require(latestTimestamp1 + _ORACLE_EXPIRATION_TIME > block.timestamp, "CC: stale data O1");
// solhint-disable-next-line not-rely-on-time
require(latestTimestamp2 + _ORACLE_EXPIRATION_TIME > block.timestamp, "CC: stale data O2");
return amount * spread * latestAnswer1.toUint256() / latestAnswer2.toUint256() / _SPREAD_DENOMINATOR;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
/// @title A helper contract for managing nonce of tx sender
contract NonceManager {
event NonceIncreased(address indexed maker, uint256 newNonce);
mapping(address => uint256) public nonce;
/// @notice Advances nonce by one
function increaseNonce() external {
advanceNonce(1);
}
/// @notice Advances nonce by specified amount
function advanceNonce(uint8 amount) public {
uint256 newNonce = nonce[msg.sender] + amount;
nonce[msg.sender] = newNonce;
emit NonceIncreased(msg.sender, newNonce);
}
/// @notice Checks if `makerAddress` has specified `makerNonce`
/// @return Result True if `makerAddress` has specified nonce. Otherwise, false
function nonceEquals(address makerAddress, uint256 makerNonce) external view returns(bool) {
return nonce[makerAddress] == makerNonce;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/utils/Address.sol";
/// @title A helper contract for executing boolean functions on arbitrary target call results
contract PredicateHelper {
using Address for address;
/// @notice Calls every target with corresponding data
/// @return Result True if call to any target returned True. Otherwise, false
function or(address[] calldata targets, bytes[] calldata data) external view returns(bool) {
require(targets.length == data.length, "PH: input array size mismatch");
for (uint256 i = 0; i < targets.length; i++) {
bytes memory result = targets[i].functionStaticCall(data[i], "PH: 'or' subcall failed");
require(result.length == 32, "PH: invalid call result");
if (abi.decode(result, (bool))) {
return true;
}
}
return false;
}
/// @notice Calls every target with corresponding data
/// @return Result True if calls to all targets returned True. Otherwise, false
function and(address[] calldata targets, bytes[] calldata data) external view returns(bool) {
require(targets.length == data.length, "PH: input array size mismatch");
for (uint256 i = 0; i < targets.length; i++) {
bytes memory result = targets[i].functionStaticCall(data[i], "PH: 'and' subcall failed");
require(result.length == 32, "PH: invalid call result");
if (!abi.decode(result, (bool))) {
return false;
}
}
return true;
}
/// @notice Calls target with specified data and tests if it's equal to the value
/// @param value Value to test
/// @return Result True if call to target returns the same value as `value`. Otherwise, false
function eq(uint256 value, address target, bytes memory data) external view returns(bool) {
bytes memory result = target.functionStaticCall(data, "PH: eq");
require(result.length == 32, "PH: invalid call result");
return abi.decode(result, (uint256)) == value;
}
/// @notice Calls target with specified data and tests if it's lower than value
/// @param value Value to test
/// @return Result True if call to target returns value which is lower than `value`. Otherwise, false
function lt(uint256 value, address target, bytes memory data) external view returns(bool) {
bytes memory result = target.functionStaticCall(data, "PH: lt");
require(result.length == 32, "PH: invalid call result");
return abi.decode(result, (uint256)) < value;
}
/// @notice Calls target with specified data and tests if it's bigger than value
/// @param value Value to test
/// @return Result True if call to target returns value which is bigger than `value`. Otherwise, false
function gt(uint256 value, address target, bytes memory data) external view returns(bool) {
bytes memory result = target.functionStaticCall(data, "PH: gt");
require(result.length == 32, "PH: invalid call result");
return abi.decode(result, (uint256)) > value;
}
/// @notice Checks passed time against block timestamp
/// @return Result True if current block timestamp is lower than `time`. Otherwise, false
function timestampBelow(uint256 time) external view returns(bool) {
return block.timestamp < time; // solhint-disable-line not-rely-on-time
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
/// @title Interface for interactor which acts between `maker => taker` and `taker => maker` transfers.
interface InteractiveNotificationReceiver {
/// @notice Callback method that gets called after taker transferred funds to maker but before
/// the opposite transfer happened
function notifyFillOrder(
address taker,
address makerAsset,
address takerAsset,
uint256 makingAmount,
uint256 takingAmount,
bytes memory interactiveData
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
/// @title Library with gas efficient alternatives to `abi.decode`
library ArgumentsDecoder {
function decodeUint256(bytes memory data) internal pure returns(uint256) {
uint256 value;
assembly { // solhint-disable-line no-inline-assembly
value := mload(add(data, 0x20))
}
return value;
}
function decodeBool(bytes memory data) internal pure returns(bool) {
bool value;
assembly { // solhint-disable-line no-inline-assembly
value := eq(mload(add(data, 0x20)), 1)
}
return value;
}
function decodeTargetAndCalldata(bytes memory data) internal pure returns(address, bytes memory) {
address target;
bytes memory args;
assembly { // solhint-disable-line no-inline-assembly
target := mload(add(data, 0x14))
args := add(data, 0x14)
mstore(args, sub(mload(data), 0x14))
}
return (target, args);
}
function decodeTargetAndData(bytes calldata data) internal pure returns(address, bytes calldata) {
address target;
bytes calldata args;
assembly { // solhint-disable-line no-inline-assembly
target := shr(96, calldataload(data.offset))
}
args = data[20:];
return (target, args);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "./RevertReasonParser.sol";
import "../interfaces/IDaiLikePermit.sol";
/// @title Base contract with common permit handling logics
abstract contract Permitable {
function _permit(address token, bytes calldata permit) internal {
if (permit.length > 0) {
bool success;
bytes memory result;
if (permit.length == 32 * 7) {
// solhint-disable-next-line avoid-low-level-calls
(success, result) = token.call(abi.encodePacked(IERC20Permit.permit.selector, permit));
} else if (permit.length == 32 * 8) {
// solhint-disable-next-line avoid-low-level-calls
(success, result) = token.call(abi.encodePacked(IDaiLikePermit.permit.selector, permit));
} else {
revert("Wrong permit length");
}
if (!success) {
revert(RevertReasonParser.parse(result, "Permit failed: "));
}
}
}
function _permitMemory(address token, bytes memory permit) internal {
if (permit.length > 0) {
bool success;
bytes memory result;
if (permit.length == 32 * 7) {
// solhint-disable-next-line avoid-low-level-calls
(success, result) = token.call(abi.encodePacked(IERC20Permit.permit.selector, permit));
} else if (permit.length == 32 * 8) {
// solhint-disable-next-line avoid-low-level-calls
(success, result) = token.call(abi.encodePacked(IDaiLikePermit.permit.selector, permit));
} else {
revert("Wrong permit length");
}
if (!success) {
revert(RevertReasonParser.parse(result, "Permit failed: "));
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (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
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals()
external
view
returns (
uint8
);
function description()
external
view
returns (
string memory
);
function version()
external
view
returns (
uint256
);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (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
pragma solidity 0.8.10;
pragma abicoder v1;
/// @title Library that allows to parse unsuccessful arbitrary calls revert reasons.
/// See https://solidity.readthedocs.io/en/latest/control-structures.html#revert for details.
/// Note that we assume revert reason being abi-encoded as Error(string) so it may fail to parse reason
/// if structured reverts appear in the future.
///
/// All unsuccessful parsings get encoded as Unknown(data) string
library RevertReasonParser {
bytes4 constant private _PANIC_SELECTOR = bytes4(keccak256("Panic(uint256)"));
bytes4 constant private _ERROR_SELECTOR = bytes4(keccak256("Error(string)"));
function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
if (data.length >= 4) {
bytes4 selector;
assembly { // solhint-disable-line no-inline-assembly
selector := mload(add(data, 0x20))
}
// 68 = 4-byte selector + 32 bytes offset + 32 bytes length
if (selector == _ERROR_SELECTOR && data.length >= 68) {
uint256 offset;
bytes memory reason;
assembly { // solhint-disable-line no-inline-assembly
// 36 = 32 bytes data length + 4-byte selector
offset := mload(add(data, 36))
reason := add(data, add(36, offset))
}
/*
revert reason is padded up to 32 bytes with ABI encoder: Error(string)
also sometimes there is extra 32 bytes of zeros padded in the end:
https://github.com/ethereum/solidity/issues/10170
because of that we can't check for equality and instead check
that offset + string length + extra 36 bytes is less than overall data length
*/
require(data.length >= 36 + offset + reason.length, "Invalid revert reason");
return string(abi.encodePacked(prefix, "Error(", reason, ")"));
}
// 36 = 4-byte selector + 32 bytes integer
else if (selector == _PANIC_SELECTOR && data.length == 36) {
uint256 code;
assembly { // solhint-disable-line no-inline-assembly
// 36 = 32 bytes data length + 4-byte selector
code := mload(add(data, 36))
}
return string(abi.encodePacked(prefix, "Panic(", _toHex(code), ")"));
}
}
return string(abi.encodePacked(prefix, "Unknown(", _toHex(data), ")"));
}
function _toHex(uint256 value) private pure returns(string memory) {
return _toHex(abi.encodePacked(value));
}
function _toHex(bytes memory data) private pure returns(string memory) {
bytes16 alphabet = 0x30313233343536373839616263646566;
bytes memory str = new bytes(2 + data.length * 2);
str[0] = "0";
str[1] = "x";
for (uint256 i = 0; i < data.length; i++) {
str[2 * i + 2] = alphabet[uint8(data[i] >> 4)];
str[2 * i + 3] = alphabet[uint8(data[i] & 0x0f)];
}
return string(str);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
pragma abicoder v1;
/// @title Interface for DAI-style permits
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
// OpenZeppelin Contracts v4.4.0 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}{
"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[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":false,"internalType":"uint256","name":"newNonce","type":"uint256"}],"name":"NonceIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"remainingRaw","type":"uint256"}],"name":"OrderCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"maker","type":"address"},{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"remaining","type":"uint256"}],"name":"OrderFilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"makingAmount","type":"uint256"}],"name":"OrderFilledRFQ","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIMIT_ORDER_RFQ_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIMIT_ORDER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"amount","type":"uint8"}],"name":"advanceNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"and","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"arbitraryStaticCall","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderInfo","type":"uint256"}],"name":"cancelOrderRFQ","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"}],"name":"checkPredicate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AggregatorV3Interface","name":"oracle1","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"oracle2","type":"address"},{"internalType":"uint256","name":"spread","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"doublePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"eq","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"uint256","name":"thresholdAmount","type":"uint256"}],"name":"fillOrder","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"info","type":"uint256"},{"internalType":"contract IERC20","name":"makerAsset","type":"address"},{"internalType":"contract IERC20","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"internalType":"struct OrderRFQMixin.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"name":"fillOrderRFQ","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"info","type":"uint256"},{"internalType":"contract IERC20","name":"makerAsset","type":"address"},{"internalType":"contract IERC20","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"internalType":"struct OrderRFQMixin.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"}],"name":"fillOrderRFQTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"info","type":"uint256"},{"internalType":"contract IERC20","name":"makerAsset","type":"address"},{"internalType":"contract IERC20","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"internalType":"struct OrderRFQMixin.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"fillOrderRFQToWithPermit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"uint256","name":"thresholdAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"}],"name":"fillOrderTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"uint256","name":"thresholdAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"fillOrderToWithPermit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderMakerAmount","type":"uint256"},{"internalType":"uint256","name":"orderTakerAmount","type":"uint256"},{"internalType":"uint256","name":"swapTakerAmount","type":"uint256"}],"name":"getMakerAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderMakerAmount","type":"uint256"},{"internalType":"uint256","name":"orderTakerAmount","type":"uint256"},{"internalType":"uint256","name":"swapMakerAmount","type":"uint256"}],"name":"getTakerAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"gt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"internalType":"bytes","name":"getMakerAmount","type":"bytes"},{"internalType":"bytes","name":"getTakerAmount","type":"bytes"},{"internalType":"bytes","name":"predicate","type":"bytes"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"}],"internalType":"struct OrderMixin.Order","name":"order","type":"tuple"}],"name":"hashOrder","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"increaseNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"slot","type":"uint256"}],"name":"invalidatorForOrderRFQ","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"lt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"uint256","name":"makerNonce","type":"uint256"}],"name":"nonceEquals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"or","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"remaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"remainingRaw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"orderHashes","type":"bytes32[]"}],"name":"remainingsRaw","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"simulateCalls","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AggregatorV3Interface","name":"oracle","type":"address"},{"internalType":"uint256","name":"inverseAndSpread","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"singlePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"timestampBelow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101406040523480156200001257600080fd5b50604080518082018252601a81527f31696e6368204c696d6974204f726465722050726f746f636f6c0000000000006020808301918252835180850190945260018452601960f91b908401528151902060e08190527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a56101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620001068184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c05261012052506200011c92505050565b60805160a05160c05160e05161010051610120516157546200016c6000396000612bc401526000612c1301526000612bee01526000612b4701526000612b7101526000612b9b01526157546000f3fe608060405234801561001057600080fd5b506004361061020b5760003560e01c8063825caba11161012a578063bc1ed74c116100bd578063cf6fc6e31161008c578063e613330111610071578063e6133301146104e4578063f4a215c3146104f7578063fa1cb9f21461050a57600080fd5b8063cf6fc6e314610497578063d0a3b665146104d157600080fd5b8063bc1ed74c14610456578063bf15fcd814610469578063c05435f11461047c578063c53a02921461048f57600080fd5b8063a65a0e71116100f9578063a65a0e711461040a578063b244b4501461041d578063b2610fe314610430578063baba58551461044357600080fd5b8063825caba1146103b1578063871919d5146103c4578063942461bb146103d7578063961d5b1e146103f757600080fd5b806356f16124116101a257806370ae92d21161017157806370ae92d21461034957806372c244a8146103695780637e54f0921461037e5780637f29a59d1461039e57600080fd5b806356f16124146102fd5780636073cc201461031057806363592c2b14610323578063655d13cd1461033657600080fd5b806336006bf3116101de57806336006bf3146102935780633644e515146102a65780634cc4a27b146102ae57806354dd5f74146102d657600080fd5b8063057702e91461021057806306bf53d014610238578063296637bf1461026d57806332565d6114610280575b600080fd5b61022361021e3660046146fb565b61051d565b60405190151581526020015b60405180910390f35b61025f7f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f4581565b60405190815260200161022f565b61025f61027b366004614754565b610613565b61022361028e3660046146fb565b610649565b61025f6102a1366004614780565b610738565b61025f610ae1565b6102c16102bc3660046148b0565b610af0565b6040805192835260208301919091520161022f565b61025f7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a81565b61025f61030b36600461495e565b610b21565b6102c161031e366004614b3a565b610b59565b610223610331366004614c02565b421090565b6102c1610344366004614c1b565b610c0b565b61025f610357366004614c9e565b60006020819052908152604090205481565b61037c610377366004614cbb565b610c2c565b005b61025f61038c366004614c02565b60009081526001602052604090205490565b61037c6103ac366004614d23565b610c99565b61037c6103bf366004614c02565b610f4c565b6102236103d23660046146fb565b610f59565b6103ea6103e5366004614d8f565b611048565b60405161022f9190614e29565b610223610405366004614d23565b611101565b610223610418366004614e6d565b6112fd565b61037c61042b366004614e6d565b6113c1565b6102c161043e366004614ea2565b61151e565b6102c1610451366004614f3d565b611d81565b61025f610464366004614c02565b612342565b61025f610477366004614fbc565b6123e0565b61025f61048a36600461500c565b612464565b61037c6126ce565b6102236104a536600461495e565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152602081905260409020541490565b6102c16104df366004615041565b6126da565b6102236104f2366004614d23565b6126f9565b61025f610505366004614754565b6128c4565b61025f610518366004614e6d565b6128d1565b600080610580836040518060400160405280600681526020017f50483a20677400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080516020146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064015b60405180910390fd5b848180602001905181019061060791906150aa565b119150505b9392505050565b60008360018161062386866150f2565b61062d919061512f565b6106379190615147565b610641919061515e565b949350505050565b6000806106ac836040518060400160405280600681526020017f50483a20657100000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061072e91906150aa565b1495945050505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610785573d6000803e3d6000fd5b505050506040513d602081101561079b57600080fd5b5051604080517f313ce567000000000000000000000000000000000000000000000000000000008152905160ff9092169173ffffffffffffffffffffffffffffffffffffffff88169163313ce5679160048083019260209291908290030181865afa15801561080e573d6000803e3d6000fd5b505050506040513d602081101561082457600080fd5b505160ff161461089557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43433a206f7261636c6520646563696d616c7320646f6e2774206d6174636800604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156108e3573d6000803e3d6000fd5b505050506040513d60a08110156108f957600080fd5b506020810151606090910151604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051929450909250600091829173ffffffffffffffffffffffffffffffffffffffff8a169163feaf968c9160048082019260a0929091908290030181865afa15801561097c573d6000803e3d6000fd5b505050506040513d60a081101561099257600080fd5b5060208101516060909101519092509050426109b06107088561512f565b11610a1c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f31000000000000000000000000000000604482015290519081900360640190fd5b42610a296107088361512f565b11610a9557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f32000000000000000000000000000000604482015290519081900360640190fd5b633b9aca00610aa383612abd565b610aac86612abd565b610ab68a8a6150f2565b610ac091906150f2565b610aca919061515e565b610ad4919061515e565b9998505050505050505050565b6000610aeb612b2d565b905090565b600080610b028a604001518585612c61565b610b108a8a8a8a8a8a611d81565b915091509850989650505050505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602090815260408083208484529091529020545b92915050565b6000806014831015610bc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a207065726d6974206c656e67746820746f6f206c6f7700000000000060448201526064016105e9565b6000366000610bd68787612fb0565b925092509250610be7838383612c61565b610bf68e8e8e8e8e8e8e61151e565b94509450505050995099975050505050505050565b600080610c1d8888888888883361151e565b91509150965096945050505050565b33600090815260208190526040812054610c4a9060ff84169061512f565b33600081815260208181526040918290208490558151848152915193945091927ffc69110dd11eb791755e4abd6b7d281bae236de95736d38a23782814be5e10db929181900390910190a25050565b828114610d02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2061727261792073697a65206d69736d61746368000000000000000060448201526064016105e9565b60008367ffffffffffffffff811115610d1d57610d1d6145c5565b6040519080825280601f01601f191660200182016040528015610d47576020820181803683370190505b50905060005b84811015610edc57600080878784818110610d6a57610d6a615199565b9050602002016020810190610d7f9190614c9e565b73ffffffffffffffffffffffffffffffffffffffff16868685818110610da757610da7615199565b9050602002810190610db991906151c8565b604051610dc792919061522d565b6000604051808303816000865af19150503d8060008114610e04576040519150601f19603f3d011682016040523d82523d6000602084013e610e09565b606091505b5091509150818015610e1c575060008151115b15610e395780516020148015610e36575060208101516001145b91505b81610e64577f3000000000000000000000000000000000000000000000000000000000000000610e86565b7f31000000000000000000000000000000000000000000000000000000000000005b848481518110610e9857610e98615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050508080610ed49061523d565b915050610d4d565b5080604051602001610eee91906152a2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526105e991600401615331565b610f563382612fd9565b50565b600080610fbc836040518060400160405280600681526020017f50483a206c7400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014611029576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061103e91906150aa565b1095945050505050565b60606000825167ffffffffffffffff811115611066576110666145c5565b60405190808252806020026020018201604052801561108f578160200160208202803683370190505b50905060005b83518110156110fa57600160008583815181106110b4576110b4615199565b60200260200101518152602001908152602001600020548282815181106110dd576110dd615199565b6020908102919091010152806110f28161523d565b915050611095565b5092915050565b600083821461116c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156112f157600061124e85858481811061118e5761118e615199565b90506020028101906111a091906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f50483a2027616e64272073756263616c6c206661696c65640000000000000000602082015291508a9050898681811061121c5761121c615199565b90506020020160208101906112319190614c9e565b73ffffffffffffffffffffffffffffffffffffffff1691906129ac565b905080516020146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906112cf9190615344565b6112de57600092505050610641565b50806112e98161523d565b91505061116f565b50600195945050505050565b61018081015160408051808201909152601a81527f4c4f503a207072656469636174652063616c6c206661696c6564000000000000602082015260009182916113479130916129ac565b905080516020146113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c6964207072656469636174652072657475726e00000060448201526064016105e9565b602081015160011461060c565b606081015173ffffffffffffffffffffffffffffffffffffffff163314611444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a204163636573732064656e696564000000000000000000000000000060448201526064016105e9565b600061144f826128d1565b6000818152600160208190526040909120549192508114156114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4c4f503a20616c72656164792066696c6c65640000000000000000000000000060448201526064016105e9565b604080518381526020810183905233917fcbfa7d191838ece7ba4783ca3a30afd316619b7f368094b57ee7ffde9a923db1910160405180910390a25060009081526001602081905260409091205550565b60008073ffffffffffffffffffffffffffffffffffffffff831661159e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b60006115a98a6128d1565b600081815260016020819052604090912054919250811415611627576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2072656d61696e696e6720616d6f756e74206973203000000000000060448201526064016105e9565b60a08b015173ffffffffffffffffffffffffffffffffffffffff161580611667575060a08b015173ffffffffffffffffffffffffffffffffffffffff1633145b6116cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b8061185a576117178b60600151838c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b61177d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b8a60c00151905060148b6101a001515110611855576000806117ce8d6101a0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091506117dc8282613294565b60008481526001602052604090205415611852576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a207265656e7472616e6379206465746563746564000000000000000060448201526064016105e9565b50505b61187d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b6101808b015151156118f8576118928b6112fd565b6118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207072656469636174652072657475726e65642066616c736500000060448201526064016105e9565b861588151415611964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c4f503a206f6e6c79206f6e6520616d6f756e742073686f756c64206265203060448201526064016105e9565b86611a13578781811115611976578198505b61198f8c61016001518d60c001518b8f60e0015161351c565b975061199b89886150f2565b6119a5828a6150f2565b1115611a0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e7420746f6f2068696768000000000060448201526064016105e9565b50611ad8565b6000879050611a318c61014001518d60e001518a8f60c0015161351c565b985081891115611a5a57819850611a578c61016001518d60c001518b8f60e0015161351c565b97505b611a6488886150f2565b611a6e828b6150f2565b1015611ad6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a206d616b696e6720616d6f756e7420746f6f206c6f7700000000000060448201526064016105e9565b505b600088118015611ae85750600087115b611b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b600082815260016020818152604092839020938b900391820190935581518481529283018190529133917fb9ed0243fdf00f0545c63a0af8850c090d86bb46682baec4bf3c496814fe4f02910160405180910390a25060408a015160808b0151611c4691907f23b872dd0000000000000000000000000000000000000000000000000000000090339073ffffffffffffffffffffffffffffffffffffffff1615611bfc578d60800151611c02565b8d606001515b6101208f0151604051611c3294939273ffffffffffffffffffffffffffffffffffffffff16918d91602001615366565b60405160208183030381529060405261368a565b60148a6101c001515110611d1457600080611c908c6101c0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091508173ffffffffffffffffffffffffffffffffffffffff1663cf21c775338e602001518f604001518d8d876040518763ffffffff1660e01b8152600401611cdf969594939291906153c3565b600060405180830381600087803b158015611cf957600080fd5b505af1158015611d0d573d6000803e3d6000fd5b5050505050505b611d718a602001516323b872dd60e01b8c6060015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168b8f6101000151604051602001611c32959493929190615366565b5094989397509295505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff8316611e01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b6060880151608089015173ffffffffffffffffffffffffffffffffffffffff161580611e465750608089015173ffffffffffffffffffffffffffffffffffffffff1633145b611eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b6000611f707f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f458b604051602001611f5592919060006101008201905083825282516020830152602083015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408601511660608501528060608601511660808501528060808601511660a0850152505060a083015160c083015260c083015160e08301529392505050565b60405160208183030381529060405280519060200120613771565b9050611fb382828b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b895167ffffffffffffffff604082901c168015806120375750804211155b61209d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a206f726465722065787069726564000000000000000000000000000060448201526064016105e9565b6120a78483612fd9565b505060a08a015160c08b0151871580156120bf575088155b156120cf57819850809750612233565b87612150578189111561213e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a206d616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b61214982828b610613565b9750612233565b886121d157808811156121bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b6121ca82828a6128c4565b9850612233565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4c4f503a20626f746820616d6f756e747320617265206e6f6e2d7a65726f000060448201526064016105e9565b50506000871180156122455750600086115b6122ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b60208a01516122d29073ffffffffffffffffffffffffffffffffffffffff1683878a6137da565b60408a01516122f99073ffffffffffffffffffffffffffffffffffffffff163384896137da565b60408051828152602081018990527fc3b639f02b125bfa160e50739b8c44eb2d1b6908e2b6d5925c6d770f2ca78127910160405180910390a15094989397509295505050505050565b600081815260016020526040812054806123b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20556e6b6e6f776e206f72646572000000000000000000000000000060448201526064016105e9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b600080612443836040518060400160405280601781526020017f41433a2061726269747261727953746174696343616c6c0000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080806020019051602081101561245a57600080fd5b5051949350505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156124b4573d6000803e3d6000fd5b505050506040513d60a08110156124ca57600080fd5b5060208101516060909101519092509050426124e86107088361512f565b1161255457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43433a207374616c652064617461000000000000000000000000000000000000604482015290519081900360640190fd5b7f80000000000000000000000000000000000000000000000000000000000000008516158015907f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87169061265257633b9aca006125b185612abd565b8973ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125fc573d6000803e3d6000fd5b505050506040513d602081101561261257600080fd5b505161261f90600a615530565b612629848a6150f2565b61263391906150f2565b61263d919061515e565b612647919061515e565b94505050505061060c565b633b9aca008873ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126a2573d6000803e3d6000fd5b505050506040513d60208110156126b857600080fd5b50516126c590600a615530565b61261f86612abd565b6126d86001610c2c565b565b6000806126eb878787878733611d81565b915091509550959350505050565b6000838214612764576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156128b857600061281485858481811061278657612786615199565b905060200281019061279891906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f50483a20276f72272073756263616c6c206661696c6564000000000000000000602082015291508a9050898681811061121c5761121c615199565b90508051602014612881576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906128959190615344565b156128a557600192505050610641565b50806128b08161523d565b915050612767565b50600095945050505050565b60008261063785846150f2565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905282905061060c7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a8285610100015180519060200120866101200151805190602001208761014001518051906020012088610160015180519060200120896101800151805190602001208a6101a00151805190602001208b6101c0015180519060200120604051602001611f559998979695949392919061553f565b6060833b612a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105e9565b6000808573ffffffffffffffffffffffffffffffffffffffff1685604051612a63919061562c565b600060405180830381855afa9150503d8060008114612a9e576040519150601f19603f3d011682016040523d82523d6000602084013e612aa3565b606091505b5091509150612ab382828661386f565b9695505050505050565b600080821215612b29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016105e9565b5090565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015612b9357507f000000000000000000000000000000000000000000000000000000000000000046145b15612bbd57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b8015612fab576000606060e0831415612d9e576040517fd505accf000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff881692879187916024018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d8e576040519150601f19603f3d011682016040523d82523d6000602084013e612d93565b606091505b509092509050612ec6565b610100831415612e5f576040517f8fcbaf0c000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff8816928791879160240183838082843780830192505050935050505060405160208183030381529060405260405180828051906020019080838360208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e67207065726d6974206c656e67746800000000000000000000000000604482015290519081900360640190fd5b81612fa857612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f6d578181015183820152602001612f55565b50505050905090810190601f168015612f9a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505b505050565b60003681843560601c8282612fc8876014818b615648565b939650945091925050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020908152604080832066ffffffffffffff600886901c16808552928190529220549091600160ff85161b918083161561308d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c4f503a20696e76616c696461746564206f726465720000000000000000000060448201526064016105e9565b60009384526020919091526040909220911790555050565b60008060006130b48585613e5d565b909250905060008160048111156130cd576130cd615672565b14801561310557508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156131155760019250505061060c565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b888860405160240161314a9291906156a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516131d3919061562c565b600060405180830381855afa9150503d806000811461320e576040519150601f19603f3d011682016040523d82523d6000602084013e613213565b606091505b5091509150818015613226575080516020145b8015613288575080517f1626ba7e000000000000000000000000000000000000000000000000000000009061326490830160209081019084016156ba565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b98975050505050505050565b8051156135185760006060825160e01415613432578373ffffffffffffffffffffffffffffffffffffffff1663d505accf60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083835b6020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040526040518082805190602001908083835b602083106133c057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613383565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613422576040519150601f19603f3d011682016040523d82523d6000602084013e613427565b606091505b5090925090506134d1565b82516101001415612e5f578373ffffffffffffffffffffffffffffffffffffffff16638fcbaf0c60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083836020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b8161351557612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b50505b5050565b600084516000141561359857838314613591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4c4f503a2077726f6e6720616d6f756e7400000000000000000000000000000060448201526064016105e9565b5080610641565b600061361286856040516020016135b09291906156fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152601a82527f4c4f503a20676574416d6f756e742063616c6c206661696c6564000000000000602083015230916129ac565b9050805160201461367f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c696420676574416d6f756e742072657475726e00000060448201526064016105e9565b602001519050610641565b60006136ec826040518060400160405280601681526020017f4c4f503a2061737365742e63616c6c206661696c6564000000000000000000008152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab578051602014801561370b575060208101516001145b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2061737365742e63616c6c2062616420726573756c7400000000000060448201526064016105e9565b6000610b5361377e612b2d565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052613515908590613edc565b6060831561387e57508161060c565b82511561388e5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e99190615331565b60606004835110613cf15760208301517fffffffff0000000000000000000000000000000000000000000000000000000081167f08c379a00000000000000000000000000000000000000000000000000000000014801561392557506044845110155b15613b265760248481015180860182018051919290919061394790849061512f565b613951919061512f565b865110156139c057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c69642072657665727420726561736f6e0000000000000000000000604482015290519081900360640190fd5b84816040516020018083805190602001908083835b60208310613a1257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016139d5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f4572726f72280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613abf57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613a82565b6001836020036101000a038019825116818451168082178552505050505050905001807f2900000000000000000000000000000000000000000000000000000000000000815250600101925050506040516020818303038152906040529350505050610b53565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f4e487b7100000000000000000000000000000000000000000000000000000000148015613b78575083516024145b15613cef57602484015183613b8c82613fe8565b6040516020018083805190602001908083835b60208310613bdc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b9f565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f50616e6963280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613c8957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613c4c565b6001836020036101000a038019825116818451168082178552505050505050905001807f29000000000000000000000000000000000000000000000000000000000000008152506001019250505060405160208183030381529060405292505050610b53565b505b81613cfb8461400e565b6040516020018083805190602001908083835b60208310613d4b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613d0e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f556e6b6e6f776e28000000000000000000000000000000000000000000000000919093019081528451600890910192850191508083835b60208310613df857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613dbb565b6001836020036101000a038019825116818451168082178552505050505050905001807f290000000000000000000000000000000000000000000000000000000000000081525060010192505050604051602081830303815290604052905092915050565b600080825160411415613e945760208301516040840151606085015160001a613e88878285856142b3565b94509450505050613ec6565b825160401415613ebe5760208301516040840151613eb38683836143cb565b935093505050613ec6565b506000905060025b9250929050565b60606106418484600085614413565b6000613f3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab5780806020019051810190613f5c9190615344565b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105e9565b6060610b5382604051602001808281526020019150506040516020818303038152906040525b80516060907f3031323334353637383961626364656600000000000000000000000000000000906000906140439060026150f2565b61404e90600261512f565b67ffffffffffffffff811115614066576140666145c5565b6040519080825280601f01601f191660200182016040528015614090576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106140c7576140c7615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061412a5761412a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b84518110156142ab5782600486838151811061417a5761417a615199565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c60f81c601081106141b6576141b6615199565b1a60f81b826141c68360026150f2565b6141d190600261512f565b815181106141e1576141e1615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508285828151811061422357614223615199565b60209101015160f81c600f166010811061423f5761423f615199565b1a60f81b8261424f8360026150f2565b61425a90600361512f565b8151811061426a5761426a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806142a38161523d565b91505061415c565b509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156142ea57506000905060036143c2565b8460ff16601b1415801561430257508460ff16601c14155b1561431357506000905060046143c2565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614367573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166143bb576000600192509250506143c2565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01614405878288856142b3565b935093505050935093915050565b6060824710156144a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105e9565b843b61450d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e9565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614536919061562c565b60006040518083038185875af1925050503d8060008114614573576040519150601f19603f3d011682016040523d82523d6000602084013e614578565b606091505b509150915061458882828661386f565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f5657600080fd5b80356145c081614593565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101e0810167ffffffffffffffff81118282101715614618576146186145c5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614665576146656145c5565b604052919050565b600082601f83011261467e57600080fd5b813567ffffffffffffffff811115614698576146986145c5565b6146c960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161461e565b8181528460208386010111156146de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561471057600080fd5b83359250602084013561472281614593565b9150604084013567ffffffffffffffff81111561473e57600080fd5b61474a8682870161466d565b9150509250925092565b60008060006060848603121561476957600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561479657600080fd5b84356147a181614593565b935060208501356147b181614593565b93969395505050506040820135916060013590565b600060e082840312156147d857600080fd5b60405160e0810181811067ffffffffffffffff821117156147fb576147fb6145c5565b60405282358152905080602083013561481381614593565b6020820152604083013561482681614593565b6040820152606083013561483981614593565b6060820152608083013561484c81614593565b8060808301525060a083013560a082015260c083013560c08201525092915050565b60008083601f84011261488057600080fd5b50813567ffffffffffffffff81111561489857600080fd5b602083019150836020828501011115613ec657600080fd5b600080600080600080600080610180898b0312156148cd57600080fd5b6148d78a8a6147c6565b975060e089013567ffffffffffffffff808211156148f457600080fd5b6149008c838d0161486e565b90995097506101008b013596506101208b013595506101408b0135915061492682614593565b9093506101608a0135908082111561493d57600080fd5b5061494a8b828c0161486e565b999c989b5096995094979396929594505050565b6000806040838503121561497157600080fd5b823561497c81614593565b946020939093013593505050565b60006101e0828403121561499d57600080fd5b6149a56145f4565b9050813581526149b7602083016145b5565b60208201526149c8604083016145b5565b60408201526149d9606083016145b5565b60608201526149ea608083016145b5565b60808201526149fb60a083016145b5565b60a082015260c082013560c082015260e082013560e08201526101008083013567ffffffffffffffff80821115614a3157600080fd5b614a3d8683870161466d565b83850152610120925082850135915080821115614a5957600080fd5b614a658683870161466d565b83850152610140925082850135915080821115614a8157600080fd5b614a8d8683870161466d565b83850152610160925082850135915080821115614aa957600080fd5b614ab58683870161466d565b83850152610180925082850135915080821115614ad157600080fd5b614add8683870161466d565b838501526101a0925082850135915080821115614af957600080fd5b614b058683870161466d565b838501526101c0925082850135915080821115614b2157600080fd5b50614b2e8582860161466d565b82840152505092915050565b600080600080600080600080600060e08a8c031215614b5857600080fd5b893567ffffffffffffffff80821115614b7057600080fd5b614b7c8d838e0161498a565b9a5060208c0135915080821115614b9257600080fd5b614b9e8d838e0161486e565b909a50985060408c0135975060608c0135965060808c0135955060a08c01359150614bc882614593565b90935060c08b01359080821115614bde57600080fd5b50614beb8c828d0161486e565b915080935050809150509295985092959850929598565b600060208284031215614c1457600080fd5b5035919050565b60008060008060008060a08789031215614c3457600080fd5b863567ffffffffffffffff80821115614c4c57600080fd5b614c588a838b0161498a565b97506020890135915080821115614c6e57600080fd5b50614c7b89828a0161486e565b979a90995096976040810135976060820135975060809091013595509350505050565b600060208284031215614cb057600080fd5b813561060c81614593565b600060208284031215614ccd57600080fd5b813560ff8116811461060c57600080fd5b60008083601f840112614cf057600080fd5b50813567ffffffffffffffff811115614d0857600080fd5b6020830191508360208260051b8501011115613ec657600080fd5b60008060008060408587031215614d3957600080fd5b843567ffffffffffffffff80821115614d5157600080fd5b614d5d88838901614cde565b90965094506020870135915080821115614d7657600080fd5b50614d8387828801614cde565b95989497509550505050565b60006020808385031215614da257600080fd5b823567ffffffffffffffff80821115614dba57600080fd5b818501915085601f830112614dce57600080fd5b813581811115614de057614de06145c5565b8060051b9150614df184830161461e565b8181529183018401918481019088841115614e0b57600080fd5b938501935b8385101561328857843582529385019390850190614e10565b6020808252825182820181905260009190848201906040850190845b81811015614e6157835183529284019291840191600101614e45565b50909695505050505050565b600060208284031215614e7f57600080fd5b813567ffffffffffffffff811115614e9657600080fd5b6106418482850161498a565b600080600080600080600060c0888a031215614ebd57600080fd5b873567ffffffffffffffff80821115614ed557600080fd5b614ee18b838c0161498a565b985060208a0135915080821115614ef757600080fd5b50614f048a828b0161486e565b90975095505060408801359350606088013592506080880135915060a0880135614f2d81614593565b8091505092959891949750929550565b6000806000806000806101608789031215614f5757600080fd5b614f6188886147c6565b955060e087013567ffffffffffffffff811115614f7d57600080fd5b614f8989828a0161486e565b90965094505061010087013592506101208701359150610140870135614fae81614593565b809150509295509295509295565b60008060408385031215614fcf57600080fd5b8235614fda81614593565b9150602083013567ffffffffffffffff811115614ff657600080fd5b6150028582860161466d565b9150509250929050565b60008060006060848603121561502157600080fd5b833561502c81614593565b95602085013595506040909401359392505050565b6000806000806000610140868803121561505a57600080fd5b61506487876147c6565b945060e086013567ffffffffffffffff81111561508057600080fd5b61508c8882890161486e565b96999098509596610100810135966101209091013595509350505050565b6000602082840312156150bc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561512a5761512a6150c3565b500290565b60008219821115615142576151426150c3565b500190565b600082821015615159576151596150c3565b500390565b600082615194577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126151fd57600080fd5b83018035915067ffffffffffffffff82111561521857600080fd5b602001915036819003821315613ec657600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561526f5761526f6150c3565b5060010190565b60005b83811015615291578181015183820152602001615279565b838111156135155750506000910152565b7f43414c4c5f524553554c54535f000000000000000000000000000000000000008152600082516152da81600d850160208701615276565b91909101600d0192915050565b600081518084526152ff816020860160208601615276565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061060c60208301846152e7565b60006020828403121561535657600080fd5b8151801515811461060c57600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000086168152846004820152836024820152826044820152600082516153b2816064850160208701615276565b919091016064019695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015280871660408401525084606083015283608083015260c060a083015261328860c08301846152e7565b600181815b8085111561546957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561544f5761544f6150c3565b8085161561545c57918102915b93841c9390800290615415565b509250929050565b60008261548057506001610b53565b8161548d57506000610b53565b81600181146154a357600281146154ad576154c9565b6001915050610b53565b60ff8411156154be576154be6150c3565b50506001821b610b53565b5060208310610133831016604e8410600b84101617156154ec575081810a610b53565b6154f68383615410565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615528576155286150c3565b029392505050565b600061060c60ff841683615471565b6000610200820190508a82528951602083015260208a015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408d01511660608501528060608d0151166080850152505060808a01516155b560a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08a015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08a015160e083015260e08a015161010083015288610120830152876101408301528661016083015285610180830152846101a0830152836101c0830152826101e08301529a9950505050505050505050565b6000825161563e818460208701615276565b9190910192915050565b6000808585111561565857600080fd5b8386111561566557600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061064160408301846152e7565b6000602082840312156156cc57600080fd5b81517fffffffff000000000000000000000000000000000000000000000000000000008116811461060c57600080fd5b6000835161570e818460208801615276565b919091019182525060200191905056fea264697066735822122009df7b6648e6254c8e6876e6c4e990013e2c23656cf75059f424ad6b65c794cd64736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061020b5760003560e01c8063825caba11161012a578063bc1ed74c116100bd578063cf6fc6e31161008c578063e613330111610071578063e6133301146104e4578063f4a215c3146104f7578063fa1cb9f21461050a57600080fd5b8063cf6fc6e314610497578063d0a3b665146104d157600080fd5b8063bc1ed74c14610456578063bf15fcd814610469578063c05435f11461047c578063c53a02921461048f57600080fd5b8063a65a0e71116100f9578063a65a0e711461040a578063b244b4501461041d578063b2610fe314610430578063baba58551461044357600080fd5b8063825caba1146103b1578063871919d5146103c4578063942461bb146103d7578063961d5b1e146103f757600080fd5b806356f16124116101a257806370ae92d21161017157806370ae92d21461034957806372c244a8146103695780637e54f0921461037e5780637f29a59d1461039e57600080fd5b806356f16124146102fd5780636073cc201461031057806363592c2b14610323578063655d13cd1461033657600080fd5b806336006bf3116101de57806336006bf3146102935780633644e515146102a65780634cc4a27b146102ae57806354dd5f74146102d657600080fd5b8063057702e91461021057806306bf53d014610238578063296637bf1461026d57806332565d6114610280575b600080fd5b61022361021e3660046146fb565b61051d565b60405190151581526020015b60405180910390f35b61025f7f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f4581565b60405190815260200161022f565b61025f61027b366004614754565b610613565b61022361028e3660046146fb565b610649565b61025f6102a1366004614780565b610738565b61025f610ae1565b6102c16102bc3660046148b0565b610af0565b6040805192835260208301919091520161022f565b61025f7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a81565b61025f61030b36600461495e565b610b21565b6102c161031e366004614b3a565b610b59565b610223610331366004614c02565b421090565b6102c1610344366004614c1b565b610c0b565b61025f610357366004614c9e565b60006020819052908152604090205481565b61037c610377366004614cbb565b610c2c565b005b61025f61038c366004614c02565b60009081526001602052604090205490565b61037c6103ac366004614d23565b610c99565b61037c6103bf366004614c02565b610f4c565b6102236103d23660046146fb565b610f59565b6103ea6103e5366004614d8f565b611048565b60405161022f9190614e29565b610223610405366004614d23565b611101565b610223610418366004614e6d565b6112fd565b61037c61042b366004614e6d565b6113c1565b6102c161043e366004614ea2565b61151e565b6102c1610451366004614f3d565b611d81565b61025f610464366004614c02565b612342565b61025f610477366004614fbc565b6123e0565b61025f61048a36600461500c565b612464565b61037c6126ce565b6102236104a536600461495e565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152602081905260409020541490565b6102c16104df366004615041565b6126da565b6102236104f2366004614d23565b6126f9565b61025f610505366004614754565b6128c4565b61025f610518366004614e6d565b6128d1565b600080610580836040518060400160405280600681526020017f50483a20677400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080516020146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064015b60405180910390fd5b848180602001905181019061060791906150aa565b119150505b9392505050565b60008360018161062386866150f2565b61062d919061512f565b6106379190615147565b610641919061515e565b949350505050565b6000806106ac836040518060400160405280600681526020017f50483a20657100000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061072e91906150aa565b1495945050505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610785573d6000803e3d6000fd5b505050506040513d602081101561079b57600080fd5b5051604080517f313ce567000000000000000000000000000000000000000000000000000000008152905160ff9092169173ffffffffffffffffffffffffffffffffffffffff88169163313ce5679160048083019260209291908290030181865afa15801561080e573d6000803e3d6000fd5b505050506040513d602081101561082457600080fd5b505160ff161461089557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43433a206f7261636c6520646563696d616c7320646f6e2774206d6174636800604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156108e3573d6000803e3d6000fd5b505050506040513d60a08110156108f957600080fd5b506020810151606090910151604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051929450909250600091829173ffffffffffffffffffffffffffffffffffffffff8a169163feaf968c9160048082019260a0929091908290030181865afa15801561097c573d6000803e3d6000fd5b505050506040513d60a081101561099257600080fd5b5060208101516060909101519092509050426109b06107088561512f565b11610a1c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f31000000000000000000000000000000604482015290519081900360640190fd5b42610a296107088361512f565b11610a9557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f32000000000000000000000000000000604482015290519081900360640190fd5b633b9aca00610aa383612abd565b610aac86612abd565b610ab68a8a6150f2565b610ac091906150f2565b610aca919061515e565b610ad4919061515e565b9998505050505050505050565b6000610aeb612b2d565b905090565b600080610b028a604001518585612c61565b610b108a8a8a8a8a8a611d81565b915091509850989650505050505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602090815260408083208484529091529020545b92915050565b6000806014831015610bc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a207065726d6974206c656e67746820746f6f206c6f7700000000000060448201526064016105e9565b6000366000610bd68787612fb0565b925092509250610be7838383612c61565b610bf68e8e8e8e8e8e8e61151e565b94509450505050995099975050505050505050565b600080610c1d8888888888883361151e565b91509150965096945050505050565b33600090815260208190526040812054610c4a9060ff84169061512f565b33600081815260208181526040918290208490558151848152915193945091927ffc69110dd11eb791755e4abd6b7d281bae236de95736d38a23782814be5e10db929181900390910190a25050565b828114610d02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2061727261792073697a65206d69736d61746368000000000000000060448201526064016105e9565b60008367ffffffffffffffff811115610d1d57610d1d6145c5565b6040519080825280601f01601f191660200182016040528015610d47576020820181803683370190505b50905060005b84811015610edc57600080878784818110610d6a57610d6a615199565b9050602002016020810190610d7f9190614c9e565b73ffffffffffffffffffffffffffffffffffffffff16868685818110610da757610da7615199565b9050602002810190610db991906151c8565b604051610dc792919061522d565b6000604051808303816000865af19150503d8060008114610e04576040519150601f19603f3d011682016040523d82523d6000602084013e610e09565b606091505b5091509150818015610e1c575060008151115b15610e395780516020148015610e36575060208101516001145b91505b81610e64577f3000000000000000000000000000000000000000000000000000000000000000610e86565b7f31000000000000000000000000000000000000000000000000000000000000005b848481518110610e9857610e98615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050508080610ed49061523d565b915050610d4d565b5080604051602001610eee91906152a2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526105e991600401615331565b610f563382612fd9565b50565b600080610fbc836040518060400160405280600681526020017f50483a206c7400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014611029576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061103e91906150aa565b1095945050505050565b60606000825167ffffffffffffffff811115611066576110666145c5565b60405190808252806020026020018201604052801561108f578160200160208202803683370190505b50905060005b83518110156110fa57600160008583815181106110b4576110b4615199565b60200260200101518152602001908152602001600020548282815181106110dd576110dd615199565b6020908102919091010152806110f28161523d565b915050611095565b5092915050565b600083821461116c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156112f157600061124e85858481811061118e5761118e615199565b90506020028101906111a091906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f50483a2027616e64272073756263616c6c206661696c65640000000000000000602082015291508a9050898681811061121c5761121c615199565b90506020020160208101906112319190614c9e565b73ffffffffffffffffffffffffffffffffffffffff1691906129ac565b905080516020146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906112cf9190615344565b6112de57600092505050610641565b50806112e98161523d565b91505061116f565b50600195945050505050565b61018081015160408051808201909152601a81527f4c4f503a207072656469636174652063616c6c206661696c6564000000000000602082015260009182916113479130916129ac565b905080516020146113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c6964207072656469636174652072657475726e00000060448201526064016105e9565b602081015160011461060c565b606081015173ffffffffffffffffffffffffffffffffffffffff163314611444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a204163636573732064656e696564000000000000000000000000000060448201526064016105e9565b600061144f826128d1565b6000818152600160208190526040909120549192508114156114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4c4f503a20616c72656164792066696c6c65640000000000000000000000000060448201526064016105e9565b604080518381526020810183905233917fcbfa7d191838ece7ba4783ca3a30afd316619b7f368094b57ee7ffde9a923db1910160405180910390a25060009081526001602081905260409091205550565b60008073ffffffffffffffffffffffffffffffffffffffff831661159e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b60006115a98a6128d1565b600081815260016020819052604090912054919250811415611627576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2072656d61696e696e6720616d6f756e74206973203000000000000060448201526064016105e9565b60a08b015173ffffffffffffffffffffffffffffffffffffffff161580611667575060a08b015173ffffffffffffffffffffffffffffffffffffffff1633145b6116cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b8061185a576117178b60600151838c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b61177d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b8a60c00151905060148b6101a001515110611855576000806117ce8d6101a0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091506117dc8282613294565b60008481526001602052604090205415611852576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a207265656e7472616e6379206465746563746564000000000000000060448201526064016105e9565b50505b61187d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b6101808b015151156118f8576118928b6112fd565b6118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207072656469636174652072657475726e65642066616c736500000060448201526064016105e9565b861588151415611964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c4f503a206f6e6c79206f6e6520616d6f756e742073686f756c64206265203060448201526064016105e9565b86611a13578781811115611976578198505b61198f8c61016001518d60c001518b8f60e0015161351c565b975061199b89886150f2565b6119a5828a6150f2565b1115611a0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e7420746f6f2068696768000000000060448201526064016105e9565b50611ad8565b6000879050611a318c61014001518d60e001518a8f60c0015161351c565b985081891115611a5a57819850611a578c61016001518d60c001518b8f60e0015161351c565b97505b611a6488886150f2565b611a6e828b6150f2565b1015611ad6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a206d616b696e6720616d6f756e7420746f6f206c6f7700000000000060448201526064016105e9565b505b600088118015611ae85750600087115b611b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b600082815260016020818152604092839020938b900391820190935581518481529283018190529133917fb9ed0243fdf00f0545c63a0af8850c090d86bb46682baec4bf3c496814fe4f02910160405180910390a25060408a015160808b0151611c4691907f23b872dd0000000000000000000000000000000000000000000000000000000090339073ffffffffffffffffffffffffffffffffffffffff1615611bfc578d60800151611c02565b8d606001515b6101208f0151604051611c3294939273ffffffffffffffffffffffffffffffffffffffff16918d91602001615366565b60405160208183030381529060405261368a565b60148a6101c001515110611d1457600080611c908c6101c0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091508173ffffffffffffffffffffffffffffffffffffffff1663cf21c775338e602001518f604001518d8d876040518763ffffffff1660e01b8152600401611cdf969594939291906153c3565b600060405180830381600087803b158015611cf957600080fd5b505af1158015611d0d573d6000803e3d6000fd5b5050505050505b611d718a602001516323b872dd60e01b8c6060015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168b8f6101000151604051602001611c32959493929190615366565b5094989397509295505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff8316611e01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b6060880151608089015173ffffffffffffffffffffffffffffffffffffffff161580611e465750608089015173ffffffffffffffffffffffffffffffffffffffff1633145b611eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b6000611f707f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f458b604051602001611f5592919060006101008201905083825282516020830152602083015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408601511660608501528060608601511660808501528060808601511660a0850152505060a083015160c083015260c083015160e08301529392505050565b60405160208183030381529060405280519060200120613771565b9050611fb382828b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b895167ffffffffffffffff604082901c168015806120375750804211155b61209d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a206f726465722065787069726564000000000000000000000000000060448201526064016105e9565b6120a78483612fd9565b505060a08a015160c08b0151871580156120bf575088155b156120cf57819850809750612233565b87612150578189111561213e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a206d616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b61214982828b610613565b9750612233565b886121d157808811156121bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b6121ca82828a6128c4565b9850612233565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4c4f503a20626f746820616d6f756e747320617265206e6f6e2d7a65726f000060448201526064016105e9565b50506000871180156122455750600086115b6122ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b60208a01516122d29073ffffffffffffffffffffffffffffffffffffffff1683878a6137da565b60408a01516122f99073ffffffffffffffffffffffffffffffffffffffff163384896137da565b60408051828152602081018990527fc3b639f02b125bfa160e50739b8c44eb2d1b6908e2b6d5925c6d770f2ca78127910160405180910390a15094989397509295505050505050565b600081815260016020526040812054806123b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20556e6b6e6f776e206f72646572000000000000000000000000000060448201526064016105e9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b600080612443836040518060400160405280601781526020017f41433a2061726269747261727953746174696343616c6c0000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080806020019051602081101561245a57600080fd5b5051949350505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156124b4573d6000803e3d6000fd5b505050506040513d60a08110156124ca57600080fd5b5060208101516060909101519092509050426124e86107088361512f565b1161255457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43433a207374616c652064617461000000000000000000000000000000000000604482015290519081900360640190fd5b7f80000000000000000000000000000000000000000000000000000000000000008516158015907f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87169061265257633b9aca006125b185612abd565b8973ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125fc573d6000803e3d6000fd5b505050506040513d602081101561261257600080fd5b505161261f90600a615530565b612629848a6150f2565b61263391906150f2565b61263d919061515e565b612647919061515e565b94505050505061060c565b633b9aca008873ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126a2573d6000803e3d6000fd5b505050506040513d60208110156126b857600080fd5b50516126c590600a615530565b61261f86612abd565b6126d86001610c2c565b565b6000806126eb878787878733611d81565b915091509550959350505050565b6000838214612764576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156128b857600061281485858481811061278657612786615199565b905060200281019061279891906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f50483a20276f72272073756263616c6c206661696c6564000000000000000000602082015291508a9050898681811061121c5761121c615199565b90508051602014612881576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906128959190615344565b156128a557600192505050610641565b50806128b08161523d565b915050612767565b50600095945050505050565b60008261063785846150f2565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905282905061060c7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a8285610100015180519060200120866101200151805190602001208761014001518051906020012088610160015180519060200120896101800151805190602001208a6101a00151805190602001208b6101c0015180519060200120604051602001611f559998979695949392919061553f565b6060833b612a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105e9565b6000808573ffffffffffffffffffffffffffffffffffffffff1685604051612a63919061562c565b600060405180830381855afa9150503d8060008114612a9e576040519150601f19603f3d011682016040523d82523d6000602084013e612aa3565b606091505b5091509150612ab382828661386f565b9695505050505050565b600080821215612b29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016105e9565b5090565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000119c71d3bbac22029622cbaec24854d3d32d282816148015612b9357507f000000000000000000000000000000000000000000000000000000000000000146145b15612bbd57507fac727df7e426c0ff0f48e0e09974c6211accea154746140423b72713e6cd46fa90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fc1d571d0a0d2c8cc249aa3a81652bc314944afb71394b861698d2fdd7f4ad1bb828401527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a560608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b8015612fab576000606060e0831415612d9e576040517fd505accf000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff881692879187916024018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d8e576040519150601f19603f3d011682016040523d82523d6000602084013e612d93565b606091505b509092509050612ec6565b610100831415612e5f576040517f8fcbaf0c000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff8816928791879160240183838082843780830192505050935050505060405160208183030381529060405260405180828051906020019080838360208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e67207065726d6974206c656e67746800000000000000000000000000604482015290519081900360640190fd5b81612fa857612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f6d578181015183820152602001612f55565b50505050905090810190601f168015612f9a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505b505050565b60003681843560601c8282612fc8876014818b615648565b939650945091925050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020908152604080832066ffffffffffffff600886901c16808552928190529220549091600160ff85161b918083161561308d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c4f503a20696e76616c696461746564206f726465720000000000000000000060448201526064016105e9565b60009384526020919091526040909220911790555050565b60008060006130b48585613e5d565b909250905060008160048111156130cd576130cd615672565b14801561310557508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156131155760019250505061060c565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b888860405160240161314a9291906156a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516131d3919061562c565b600060405180830381855afa9150503d806000811461320e576040519150601f19603f3d011682016040523d82523d6000602084013e613213565b606091505b5091509150818015613226575080516020145b8015613288575080517f1626ba7e000000000000000000000000000000000000000000000000000000009061326490830160209081019084016156ba565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b98975050505050505050565b8051156135185760006060825160e01415613432578373ffffffffffffffffffffffffffffffffffffffff1663d505accf60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083835b6020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040526040518082805190602001908083835b602083106133c057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613383565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613422576040519150601f19603f3d011682016040523d82523d6000602084013e613427565b606091505b5090925090506134d1565b82516101001415612e5f578373ffffffffffffffffffffffffffffffffffffffff16638fcbaf0c60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083836020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b8161351557612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b50505b5050565b600084516000141561359857838314613591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4c4f503a2077726f6e6720616d6f756e7400000000000000000000000000000060448201526064016105e9565b5080610641565b600061361286856040516020016135b09291906156fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152601a82527f4c4f503a20676574416d6f756e742063616c6c206661696c6564000000000000602083015230916129ac565b9050805160201461367f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c696420676574416d6f756e742072657475726e00000060448201526064016105e9565b602001519050610641565b60006136ec826040518060400160405280601681526020017f4c4f503a2061737365742e63616c6c206661696c6564000000000000000000008152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab578051602014801561370b575060208101516001145b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2061737365742e63616c6c2062616420726573756c7400000000000060448201526064016105e9565b6000610b5361377e612b2d565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052613515908590613edc565b6060831561387e57508161060c565b82511561388e5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e99190615331565b60606004835110613cf15760208301517fffffffff0000000000000000000000000000000000000000000000000000000081167f08c379a00000000000000000000000000000000000000000000000000000000014801561392557506044845110155b15613b265760248481015180860182018051919290919061394790849061512f565b613951919061512f565b865110156139c057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c69642072657665727420726561736f6e0000000000000000000000604482015290519081900360640190fd5b84816040516020018083805190602001908083835b60208310613a1257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016139d5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f4572726f72280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613abf57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613a82565b6001836020036101000a038019825116818451168082178552505050505050905001807f2900000000000000000000000000000000000000000000000000000000000000815250600101925050506040516020818303038152906040529350505050610b53565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f4e487b7100000000000000000000000000000000000000000000000000000000148015613b78575083516024145b15613cef57602484015183613b8c82613fe8565b6040516020018083805190602001908083835b60208310613bdc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b9f565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f50616e6963280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613c8957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613c4c565b6001836020036101000a038019825116818451168082178552505050505050905001807f29000000000000000000000000000000000000000000000000000000000000008152506001019250505060405160208183030381529060405292505050610b53565b505b81613cfb8461400e565b6040516020018083805190602001908083835b60208310613d4b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613d0e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f556e6b6e6f776e28000000000000000000000000000000000000000000000000919093019081528451600890910192850191508083835b60208310613df857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613dbb565b6001836020036101000a038019825116818451168082178552505050505050905001807f290000000000000000000000000000000000000000000000000000000000000081525060010192505050604051602081830303815290604052905092915050565b600080825160411415613e945760208301516040840151606085015160001a613e88878285856142b3565b94509450505050613ec6565b825160401415613ebe5760208301516040840151613eb38683836143cb565b935093505050613ec6565b506000905060025b9250929050565b60606106418484600085614413565b6000613f3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab5780806020019051810190613f5c9190615344565b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105e9565b6060610b5382604051602001808281526020019150506040516020818303038152906040525b80516060907f3031323334353637383961626364656600000000000000000000000000000000906000906140439060026150f2565b61404e90600261512f565b67ffffffffffffffff811115614066576140666145c5565b6040519080825280601f01601f191660200182016040528015614090576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106140c7576140c7615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061412a5761412a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b84518110156142ab5782600486838151811061417a5761417a615199565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c60f81c601081106141b6576141b6615199565b1a60f81b826141c68360026150f2565b6141d190600261512f565b815181106141e1576141e1615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508285828151811061422357614223615199565b60209101015160f81c600f166010811061423f5761423f615199565b1a60f81b8261424f8360026150f2565b61425a90600361512f565b8151811061426a5761426a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806142a38161523d565b91505061415c565b509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156142ea57506000905060036143c2565b8460ff16601b1415801561430257508460ff16601c14155b1561431357506000905060046143c2565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614367573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166143bb576000600192509250506143c2565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01614405878288856142b3565b935093505050935093915050565b6060824710156144a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105e9565b843b61450d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e9565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614536919061562c565b60006040518083038185875af1925050503d8060008114614573576040519150601f19603f3d011682016040523d82523d6000602084013e614578565b606091505b509150915061458882828661386f565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f5657600080fd5b80356145c081614593565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101e0810167ffffffffffffffff81118282101715614618576146186145c5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614665576146656145c5565b604052919050565b600082601f83011261467e57600080fd5b813567ffffffffffffffff811115614698576146986145c5565b6146c960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161461e565b8181528460208386010111156146de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561471057600080fd5b83359250602084013561472281614593565b9150604084013567ffffffffffffffff81111561473e57600080fd5b61474a8682870161466d565b9150509250925092565b60008060006060848603121561476957600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561479657600080fd5b84356147a181614593565b935060208501356147b181614593565b93969395505050506040820135916060013590565b600060e082840312156147d857600080fd5b60405160e0810181811067ffffffffffffffff821117156147fb576147fb6145c5565b60405282358152905080602083013561481381614593565b6020820152604083013561482681614593565b6040820152606083013561483981614593565b6060820152608083013561484c81614593565b8060808301525060a083013560a082015260c083013560c08201525092915050565b60008083601f84011261488057600080fd5b50813567ffffffffffffffff81111561489857600080fd5b602083019150836020828501011115613ec657600080fd5b600080600080600080600080610180898b0312156148cd57600080fd5b6148d78a8a6147c6565b975060e089013567ffffffffffffffff808211156148f457600080fd5b6149008c838d0161486e565b90995097506101008b013596506101208b013595506101408b0135915061492682614593565b9093506101608a0135908082111561493d57600080fd5b5061494a8b828c0161486e565b999c989b5096995094979396929594505050565b6000806040838503121561497157600080fd5b823561497c81614593565b946020939093013593505050565b60006101e0828403121561499d57600080fd5b6149a56145f4565b9050813581526149b7602083016145b5565b60208201526149c8604083016145b5565b60408201526149d9606083016145b5565b60608201526149ea608083016145b5565b60808201526149fb60a083016145b5565b60a082015260c082013560c082015260e082013560e08201526101008083013567ffffffffffffffff80821115614a3157600080fd5b614a3d8683870161466d565b83850152610120925082850135915080821115614a5957600080fd5b614a658683870161466d565b83850152610140925082850135915080821115614a8157600080fd5b614a8d8683870161466d565b83850152610160925082850135915080821115614aa957600080fd5b614ab58683870161466d565b83850152610180925082850135915080821115614ad157600080fd5b614add8683870161466d565b838501526101a0925082850135915080821115614af957600080fd5b614b058683870161466d565b838501526101c0925082850135915080821115614b2157600080fd5b50614b2e8582860161466d565b82840152505092915050565b600080600080600080600080600060e08a8c031215614b5857600080fd5b893567ffffffffffffffff80821115614b7057600080fd5b614b7c8d838e0161498a565b9a5060208c0135915080821115614b9257600080fd5b614b9e8d838e0161486e565b909a50985060408c0135975060608c0135965060808c0135955060a08c01359150614bc882614593565b90935060c08b01359080821115614bde57600080fd5b50614beb8c828d0161486e565b915080935050809150509295985092959850929598565b600060208284031215614c1457600080fd5b5035919050565b60008060008060008060a08789031215614c3457600080fd5b863567ffffffffffffffff80821115614c4c57600080fd5b614c588a838b0161498a565b97506020890135915080821115614c6e57600080fd5b50614c7b89828a0161486e565b979a90995096976040810135976060820135975060809091013595509350505050565b600060208284031215614cb057600080fd5b813561060c81614593565b600060208284031215614ccd57600080fd5b813560ff8116811461060c57600080fd5b60008083601f840112614cf057600080fd5b50813567ffffffffffffffff811115614d0857600080fd5b6020830191508360208260051b8501011115613ec657600080fd5b60008060008060408587031215614d3957600080fd5b843567ffffffffffffffff80821115614d5157600080fd5b614d5d88838901614cde565b90965094506020870135915080821115614d7657600080fd5b50614d8387828801614cde565b95989497509550505050565b60006020808385031215614da257600080fd5b823567ffffffffffffffff80821115614dba57600080fd5b818501915085601f830112614dce57600080fd5b813581811115614de057614de06145c5565b8060051b9150614df184830161461e565b8181529183018401918481019088841115614e0b57600080fd5b938501935b8385101561328857843582529385019390850190614e10565b6020808252825182820181905260009190848201906040850190845b81811015614e6157835183529284019291840191600101614e45565b50909695505050505050565b600060208284031215614e7f57600080fd5b813567ffffffffffffffff811115614e9657600080fd5b6106418482850161498a565b600080600080600080600060c0888a031215614ebd57600080fd5b873567ffffffffffffffff80821115614ed557600080fd5b614ee18b838c0161498a565b985060208a0135915080821115614ef757600080fd5b50614f048a828b0161486e565b90975095505060408801359350606088013592506080880135915060a0880135614f2d81614593565b8091505092959891949750929550565b6000806000806000806101608789031215614f5757600080fd5b614f6188886147c6565b955060e087013567ffffffffffffffff811115614f7d57600080fd5b614f8989828a0161486e565b90965094505061010087013592506101208701359150610140870135614fae81614593565b809150509295509295509295565b60008060408385031215614fcf57600080fd5b8235614fda81614593565b9150602083013567ffffffffffffffff811115614ff657600080fd5b6150028582860161466d565b9150509250929050565b60008060006060848603121561502157600080fd5b833561502c81614593565b95602085013595506040909401359392505050565b6000806000806000610140868803121561505a57600080fd5b61506487876147c6565b945060e086013567ffffffffffffffff81111561508057600080fd5b61508c8882890161486e565b96999098509596610100810135966101209091013595509350505050565b6000602082840312156150bc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561512a5761512a6150c3565b500290565b60008219821115615142576151426150c3565b500190565b600082821015615159576151596150c3565b500390565b600082615194577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126151fd57600080fd5b83018035915067ffffffffffffffff82111561521857600080fd5b602001915036819003821315613ec657600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561526f5761526f6150c3565b5060010190565b60005b83811015615291578181015183820152602001615279565b838111156135155750506000910152565b7f43414c4c5f524553554c54535f000000000000000000000000000000000000008152600082516152da81600d850160208701615276565b91909101600d0192915050565b600081518084526152ff816020860160208601615276565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061060c60208301846152e7565b60006020828403121561535657600080fd5b8151801515811461060c57600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000086168152846004820152836024820152826044820152600082516153b2816064850160208701615276565b919091016064019695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015280871660408401525084606083015283608083015260c060a083015261328860c08301846152e7565b600181815b8085111561546957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561544f5761544f6150c3565b8085161561545c57918102915b93841c9390800290615415565b509250929050565b60008261548057506001610b53565b8161548d57506000610b53565b81600181146154a357600281146154ad576154c9565b6001915050610b53565b60ff8411156154be576154be6150c3565b50506001821b610b53565b5060208310610133831016604e8410600b84101617156154ec575081810a610b53565b6154f68383615410565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615528576155286150c3565b029392505050565b600061060c60ff841683615471565b6000610200820190508a82528951602083015260208a015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408d01511660608501528060608d0151166080850152505060808a01516155b560a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08a015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08a015160e083015260e08a015161010083015288610120830152876101408301528661016083015285610180830152846101a0830152836101c0830152826101e08301529a9950505050505050505050565b6000825161563e818460208701615276565b9190910192915050565b6000808585111561565857600080fd5b8386111561566557600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061064160408301846152e7565b6000602082840312156156cc57600080fd5b81517fffffffff000000000000000000000000000000000000000000000000000000008116811461060c57600080fd5b6000835161570e818460208801615276565b919091019182525060200191905056fea264697066735822122009df7b6648e6254c8e6876e6c4e990013e2c23656cf75059f424ad6b65c794cd64736f6c634300080a0033
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.Net Worth in USD
$4.08
Net Worth in ETH
0.002099
Token Allocations
ETH
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BASE | 100.00% | $1,944.48 | 0.0021 | $4.08 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.