Overview
POL Balance
0 POL
POL Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 43,432 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Fill Order | 65225930 | 38 hrs ago | IN | 0 POL | 0.0240302 | ||||
Fill Order | 64950694 | 8 days ago | IN | 0 POL | 0.02631072 | ||||
Fill Order | 64079713 | 30 days ago | IN | 0 POL | 0.1109051 | ||||
Fill Order | 64079683 | 30 days ago | IN | 0 POL | 0.13749103 | ||||
Fill Order | 60436397 | 121 days ago | IN | 0 POL | 0.02473162 | ||||
Fill Order | 60436373 | 121 days ago | IN | 0 POL | 0.02682532 | ||||
Fill Order | 57142229 | 204 days ago | IN | 0 POL | 0.02620341 | ||||
Fill Order | 57142023 | 204 days ago | IN | 0 POL | 0.0400607 | ||||
Fill Order | 57141971 | 204 days ago | IN | 0 POL | 0.02644559 | ||||
Fill Order | 56604913 | 218 days ago | IN | 0 POL | 0.00626459 | ||||
Fill Order | 56604899 | 218 days ago | IN | 0 POL | 0.00664059 | ||||
Fill Order | 56604890 | 218 days ago | IN | 0 POL | 0.00602623 | ||||
Fill Order | 56604286 | 218 days ago | IN | 0 POL | 0.02394084 | ||||
Fill Order | 56347485 | 225 days ago | IN | 0 POL | 0.03296075 | ||||
Fill Order | 55541574 | 246 days ago | IN | 0 POL | 0.01767461 | ||||
Fill Order | 55541558 | 246 days ago | IN | 0 POL | 0.01821598 | ||||
Fill Order | 55541544 | 246 days ago | IN | 0 POL | 0.02271334 | ||||
Fill Order | 55541537 | 246 days ago | IN | 0 POL | 0.02081228 | ||||
Fill Order | 55541333 | 246 days ago | IN | 0 POL | 0.07705029 | ||||
Fill Order | 55280797 | 253 days ago | IN | 0 POL | 0.04254973 | ||||
Fill Order | 55280768 | 253 days ago | IN | 0 POL | 0.03101962 | ||||
Fill Order | 55280669 | 253 days ago | IN | 0 POL | 0.10811927 | ||||
Fill Order | 55006562 | 260 days ago | IN | 0 POL | 0.00604518 | ||||
Fill Order | 54751773 | 267 days ago | IN | 0 POL | 0.01290227 | ||||
Fill Order | 54751763 | 267 days ago | IN | 0 POL | 0.01276309 |
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
[{"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
0x608060405234801561001057600080fd5b506004361061020b5760003560e01c8063825caba11161012a578063bc1ed74c116100bd578063cf6fc6e31161008c578063e613330111610071578063e6133301146104e4578063f4a215c3146104f7578063fa1cb9f21461050a57600080fd5b8063cf6fc6e314610497578063d0a3b665146104d157600080fd5b8063bc1ed74c14610456578063bf15fcd814610469578063c05435f11461047c578063c53a02921461048f57600080fd5b8063a65a0e71116100f9578063a65a0e711461040a578063b244b4501461041d578063b2610fe314610430578063baba58551461044357600080fd5b8063825caba1146103b1578063871919d5146103c4578063942461bb146103d7578063961d5b1e146103f757600080fd5b806356f16124116101a257806370ae92d21161017157806370ae92d21461034957806372c244a8146103695780637e54f0921461037e5780637f29a59d1461039e57600080fd5b806356f16124146102fd5780636073cc201461031057806363592c2b14610323578063655d13cd1461033657600080fd5b806336006bf3116101de57806336006bf3146102935780633644e515146102a65780634cc4a27b146102ae57806354dd5f74146102d657600080fd5b8063057702e91461021057806306bf53d014610238578063296637bf1461026d57806332565d6114610280575b600080fd5b61022361021e3660046146fb565b61051d565b60405190151581526020015b60405180910390f35b61025f7f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f4581565b60405190815260200161022f565b61025f61027b366004614754565b610613565b61022361028e3660046146fb565b610649565b61025f6102a1366004614780565b610738565b61025f610ae1565b6102c16102bc3660046148b0565b610af0565b6040805192835260208301919091520161022f565b61025f7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a81565b61025f61030b36600461495e565b610b21565b6102c161031e366004614b3a565b610b59565b610223610331366004614c02565b421090565b6102c1610344366004614c1b565b610c0b565b61025f610357366004614c9e565b60006020819052908152604090205481565b61037c610377366004614cbb565b610c2c565b005b61025f61038c366004614c02565b60009081526001602052604090205490565b61037c6103ac366004614d23565b610c99565b61037c6103bf366004614c02565b610f4c565b6102236103d23660046146fb565b610f59565b6103ea6103e5366004614d8f565b611048565b60405161022f9190614e29565b610223610405366004614d23565b611101565b610223610418366004614e6d565b6112fd565b61037c61042b366004614e6d565b6113c1565b6102c161043e366004614ea2565b61151e565b6102c1610451366004614f3d565b611d81565b61025f610464366004614c02565b612342565b61025f610477366004614fbc565b6123e0565b61025f61048a36600461500c565b612464565b61037c6126ce565b6102236104a536600461495e565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152602081905260409020541490565b6102c16104df366004615041565b6126da565b6102236104f2366004614d23565b6126f9565b61025f610505366004614754565b6128c4565b61025f610518366004614e6d565b6128d1565b600080610580836040518060400160405280600681526020017f50483a20677400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080516020146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064015b60405180910390fd5b848180602001905181019061060791906150aa565b119150505b9392505050565b60008360018161062386866150f2565b61062d919061512f565b6106379190615147565b610641919061515e565b949350505050565b6000806106ac836040518060400160405280600681526020017f50483a20657100000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061072e91906150aa565b1495945050505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610785573d6000803e3d6000fd5b505050506040513d602081101561079b57600080fd5b5051604080517f313ce567000000000000000000000000000000000000000000000000000000008152905160ff9092169173ffffffffffffffffffffffffffffffffffffffff88169163313ce5679160048083019260209291908290030181865afa15801561080e573d6000803e3d6000fd5b505050506040513d602081101561082457600080fd5b505160ff161461089557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43433a206f7261636c6520646563696d616c7320646f6e2774206d6174636800604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156108e3573d6000803e3d6000fd5b505050506040513d60a08110156108f957600080fd5b506020810151606090910151604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051929450909250600091829173ffffffffffffffffffffffffffffffffffffffff8a169163feaf968c9160048082019260a0929091908290030181865afa15801561097c573d6000803e3d6000fd5b505050506040513d60a081101561099257600080fd5b5060208101516060909101519092509050426109b06107088561512f565b11610a1c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f31000000000000000000000000000000604482015290519081900360640190fd5b42610a296107088361512f565b11610a9557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43433a207374616c652064617461204f32000000000000000000000000000000604482015290519081900360640190fd5b633b9aca00610aa383612abd565b610aac86612abd565b610ab68a8a6150f2565b610ac091906150f2565b610aca919061515e565b610ad4919061515e565b9998505050505050505050565b6000610aeb612b2d565b905090565b600080610b028a604001518585612c61565b610b108a8a8a8a8a8a611d81565b915091509850989650505050505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602090815260408083208484529091529020545b92915050565b6000806014831015610bc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a207065726d6974206c656e67746820746f6f206c6f7700000000000060448201526064016105e9565b6000366000610bd68787612fb0565b925092509250610be7838383612c61565b610bf68e8e8e8e8e8e8e61151e565b94509450505050995099975050505050505050565b600080610c1d8888888888883361151e565b91509150965096945050505050565b33600090815260208190526040812054610c4a9060ff84169061512f565b33600081815260208181526040918290208490558151848152915193945091927ffc69110dd11eb791755e4abd6b7d281bae236de95736d38a23782814be5e10db929181900390910190a25050565b828114610d02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2061727261792073697a65206d69736d61746368000000000000000060448201526064016105e9565b60008367ffffffffffffffff811115610d1d57610d1d6145c5565b6040519080825280601f01601f191660200182016040528015610d47576020820181803683370190505b50905060005b84811015610edc57600080878784818110610d6a57610d6a615199565b9050602002016020810190610d7f9190614c9e565b73ffffffffffffffffffffffffffffffffffffffff16868685818110610da757610da7615199565b9050602002810190610db991906151c8565b604051610dc792919061522d565b6000604051808303816000865af19150503d8060008114610e04576040519150601f19603f3d011682016040523d82523d6000602084013e610e09565b606091505b5091509150818015610e1c575060008151115b15610e395780516020148015610e36575060208101516001145b91505b81610e64577f3000000000000000000000000000000000000000000000000000000000000000610e86565b7f31000000000000000000000000000000000000000000000000000000000000005b848481518110610e9857610e98615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050508080610ed49061523d565b915050610d4d565b5080604051602001610eee91906152a2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526105e991600401615331565b610f563382612fd9565b50565b600080610fbc836040518060400160405280600681526020017f50483a206c7400000000000000000000000000000000000000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b90508051602014611029576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b848180602001905181019061103e91906150aa565b1095945050505050565b60606000825167ffffffffffffffff811115611066576110666145c5565b60405190808252806020026020018201604052801561108f578160200160208202803683370190505b50905060005b83518110156110fa57600160008583815181106110b4576110b4615199565b60200260200101518152602001908152602001600020548282815181106110dd576110dd615199565b6020908102919091010152806110f28161523d565b915050611095565b5092915050565b600083821461116c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156112f157600061124e85858481811061118e5761118e615199565b90506020028101906111a091906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f50483a2027616e64272073756263616c6c206661696c65640000000000000000602082015291508a9050898681811061121c5761121c615199565b90506020020160208101906112319190614c9e565b73ffffffffffffffffffffffffffffffffffffffff1691906129ac565b905080516020146112bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906112cf9190615344565b6112de57600092505050610641565b50806112e98161523d565b91505061116f565b50600195945050505050565b61018081015160408051808201909152601a81527f4c4f503a207072656469636174652063616c6c206661696c6564000000000000602082015260009182916113479130916129ac565b905080516020146113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c6964207072656469636174652072657475726e00000060448201526064016105e9565b602081015160011461060c565b606081015173ffffffffffffffffffffffffffffffffffffffff163314611444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a204163636573732064656e696564000000000000000000000000000060448201526064016105e9565b600061144f826128d1565b6000818152600160208190526040909120549192508114156114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4c4f503a20616c72656164792066696c6c65640000000000000000000000000060448201526064016105e9565b604080518381526020810183905233917fcbfa7d191838ece7ba4783ca3a30afd316619b7f368094b57ee7ffde9a923db1910160405180910390a25060009081526001602081905260409091205550565b60008073ffffffffffffffffffffffffffffffffffffffff831661159e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b60006115a98a6128d1565b600081815260016020819052604090912054919250811415611627576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2072656d61696e696e6720616d6f756e74206973203000000000000060448201526064016105e9565b60a08b015173ffffffffffffffffffffffffffffffffffffffff161580611667575060a08b015173ffffffffffffffffffffffffffffffffffffffff1633145b6116cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b8061185a576117178b60600151838c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b61177d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b8a60c00151905060148b6101a001515110611855576000806117ce8d6101a0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091506117dc8282613294565b60008481526001602052604090205415611852576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a207265656e7472616e6379206465746563746564000000000000000060448201526064016105e9565b50505b61187d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b6101808b015151156118f8576118928b6112fd565b6118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207072656469636174652072657475726e65642066616c736500000060448201526064016105e9565b861588151415611964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c4f503a206f6e6c79206f6e6520616d6f756e742073686f756c64206265203060448201526064016105e9565b86611a13578781811115611976578198505b61198f8c61016001518d60c001518b8f60e0015161351c565b975061199b89886150f2565b6119a5828a6150f2565b1115611a0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e7420746f6f2068696768000000000060448201526064016105e9565b50611ad8565b6000879050611a318c61014001518d60e001518a8f60c0015161351c565b985081891115611a5a57819850611a578c61016001518d60c001518b8f60e0015161351c565b97505b611a6488886150f2565b611a6e828b6150f2565b1015611ad6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a206d616b696e6720616d6f756e7420746f6f206c6f7700000000000060448201526064016105e9565b505b600088118015611ae85750600087115b611b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b600082815260016020818152604092839020938b900391820190935581518481529283018190529133917fb9ed0243fdf00f0545c63a0af8850c090d86bb46682baec4bf3c496814fe4f02910160405180910390a25060408a015160808b0151611c4691907f23b872dd0000000000000000000000000000000000000000000000000000000090339073ffffffffffffffffffffffffffffffffffffffff1615611bfc578d60800151611c02565b8d606001515b6101208f0151604051611c3294939273ffffffffffffffffffffffffffffffffffffffff16918d91602001615366565b60405160208183030381529060405261368a565b60148a6101c001515110611d1457600080611c908c6101c0015160148101805191517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec0181529091565b915091508173ffffffffffffffffffffffffffffffffffffffff1663cf21c775338e602001518f604001518d8d876040518763ffffffff1660e01b8152600401611cdf969594939291906153c3565b600060405180830381600087803b158015611cf957600080fd5b505af1158015611d0d573d6000803e3d6000fd5b5050505050505b611d718a602001516323b872dd60e01b8c6060015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168b8f6101000151604051602001611c32959493929190615366565b5094989397509295505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff8316611e01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a207a65726f2074617267657420697320666f7262696464656e00000060448201526064016105e9565b6060880151608089015173ffffffffffffffffffffffffffffffffffffffff161580611e465750608089015173ffffffffffffffffffffffffffffffffffffffff1633145b611eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a2070726976617465206f72646572000000000000000000000000000060448201526064016105e9565b6000611f707f74ab4f0cde46aaf927859983f7d04002116dd057d4c4941f6dbfb775c3e31f458b604051602001611f5592919060006101008201905083825282516020830152602083015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408601511660608501528060608601511660808501528060808601511660a0850152505060a083015160c083015260c083015160e08301529392505050565b60405160208183030381529060405280519060200120613771565b9050611fb382828b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130a592505050565b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20626164207369676e6174757265000000000000000000000000000060448201526064016105e9565b895167ffffffffffffffff604082901c168015806120375750804211155b61209d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a206f726465722065787069726564000000000000000000000000000060448201526064016105e9565b6120a78483612fd9565b505060a08a015160c08b0151871580156120bf575088155b156120cf57819850809750612233565b87612150578189111561213e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a206d616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b61214982828b610613565b9750612233565b886121d157808811156121bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4c4f503a2074616b696e6720616d6f756e74206578636565646564000000000060448201526064016105e9565b6121ca82828a6128c4565b9850612233565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4c4f503a20626f746820616d6f756e747320617265206e6f6e2d7a65726f000060448201526064016105e9565b50506000871180156122455750600086115b6122ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c4f503a2063616e27742073776170203020616d6f756e74000000000000000060448201526064016105e9565b60208a01516122d29073ffffffffffffffffffffffffffffffffffffffff1683878a6137da565b60408a01516122f99073ffffffffffffffffffffffffffffffffffffffff163384896137da565b60408051828152602081018990527fc3b639f02b125bfa160e50739b8c44eb2d1b6908e2b6d5925c6d770f2ca78127910160405180910390a15094989397509295505050505050565b600081815260016020526040812054806123b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c4f503a20556e6b6e6f776e206f72646572000000000000000000000000000060448201526064016105e9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b600080612443836040518060400160405280601781526020017f41433a2061726269747261727953746174696343616c6c0000000000000000008152508673ffffffffffffffffffffffffffffffffffffffff166129ac9092919063ffffffff16565b905080806020019051602081101561245a57600080fd5b5051949350505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156124b4573d6000803e3d6000fd5b505050506040513d60a08110156124ca57600080fd5b5060208101516060909101519092509050426124e86107088361512f565b1161255457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43433a207374616c652064617461000000000000000000000000000000000000604482015290519081900360640190fd5b7f80000000000000000000000000000000000000000000000000000000000000008516158015907f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87169061265257633b9aca006125b185612abd565b8973ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125fc573d6000803e3d6000fd5b505050506040513d602081101561261257600080fd5b505161261f90600a615530565b612629848a6150f2565b61263391906150f2565b61263d919061515e565b612647919061515e565b94505050505061060c565b633b9aca008873ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126a2573d6000803e3d6000fd5b505050506040513d60208110156126b857600080fd5b50516126c590600a615530565b61261f86612abd565b6126d86001610c2c565b565b6000806126eb878787878733611d81565b915091509550959350505050565b6000838214612764576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50483a20696e7075742061727261792073697a65206d69736d6174636800000060448201526064016105e9565b60005b848110156128b857600061281485858481811061278657612786615199565b905060200281019061279891906151c8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f50483a20276f72272073756263616c6c206661696c6564000000000000000000602082015291508a9050898681811061121c5761121c615199565b90508051602014612881576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50483a20696e76616c69642063616c6c20726573756c7400000000000000000060448201526064016105e9565b808060200190518101906128959190615344565b156128a557600192505050610641565b50806128b08161523d565b915050612767565b50600095945050505050565b60008261063785846150f2565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905282905061060c7f7b63e94209420c4f6a2a8ca90b36938c948908697db47a5dc7f8e692ead4991a8285610100015180519060200120866101200151805190602001208761014001518051906020012088610160015180519060200120896101800151805190602001208a6101a00151805190602001208b6101c0015180519060200120604051602001611f559998979695949392919061553f565b6060833b612a3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105e9565b6000808573ffffffffffffffffffffffffffffffffffffffff1685604051612a63919061562c565b600060405180830381855afa9150503d8060008114612a9e576040519150601f19603f3d011682016040523d82523d6000602084013e612aa3565b606091505b5091509150612ab382828661386f565b9695505050505050565b600080821215612b29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016105e9565b5090565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094bc2a1c732bcad7343b25af48385fe76e08734f16148015612b9357507f000000000000000000000000000000000000000000000000000000000000008946145b15612bbd57507fc78ddd286a11d8859cf5f148d386df5ded5c69eeb3ac6106bc7d0da17f32505590565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fc1d571d0a0d2c8cc249aa3a81652bc314944afb71394b861698d2fdd7f4ad1bb828401527fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a560608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b8015612fab576000606060e0831415612d9e576040517fd505accf000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff881692879187916024018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d8e576040519150601f19603f3d011682016040523d82523d6000602084013e612d93565b606091505b509092509050612ec6565b610100831415612e5f576040517f8fcbaf0c000000000000000000000000000000000000000000000000000000006020820181815273ffffffffffffffffffffffffffffffffffffffff8816928791879160240183838082843780830192505050935050505060405160208183030381529060405260405180828051906020019080838360208310612d2c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612cef565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e67207065726d6974206c656e67746800000000000000000000000000604482015290519081900360640190fd5b81612fa857612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f6d578181015183820152602001612f55565b50505050905090810190601f168015612f9a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505b505050565b60003681843560601c8282612fc8876014818b615648565b939650945091925050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020908152604080832066ffffffffffffff600886901c16808552928190529220549091600160ff85161b918083161561308d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c4f503a20696e76616c696461746564206f726465720000000000000000000060448201526064016105e9565b60009384526020919091526040909220911790555050565b60008060006130b48585613e5d565b909250905060008160048111156130cd576130cd615672565b14801561310557508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156131155760019250505061060c565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b888860405160240161314a9291906156a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516131d3919061562c565b600060405180830381855afa9150503d806000811461320e576040519150601f19603f3d011682016040523d82523d6000602084013e613213565b606091505b5091509150818015613226575080516020145b8015613288575080517f1626ba7e000000000000000000000000000000000000000000000000000000009061326490830160209081019084016156ba565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b98975050505050505050565b8051156135185760006060825160e01415613432578373ffffffffffffffffffffffffffffffffffffffff1663d505accf60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083835b6020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040526040518082805190602001908083835b602083106133c057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613383565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613422576040519150601f19603f3d011682016040523d82523d6000602084013e613427565b606091505b5090925090506134d1565b82516101001415612e5f578373ffffffffffffffffffffffffffffffffffffffff16638fcbaf0c60e01b8460405160200180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040182805190602001908083836020831061333e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613301565b8161351557612f0a816040518060400160405280600f81526020017f5065726d6974206661696c65643a2000000000000000000000000000000000008152506138c2565b50505b5050565b600084516000141561359857838314613591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4c4f503a2077726f6e6720616d6f756e7400000000000000000000000000000060448201526064016105e9565b5080610641565b600061361286856040516020016135b09291906156fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152601a82527f4c4f503a20676574416d6f756e742063616c6c206661696c6564000000000000602083015230916129ac565b9050805160201461367f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4c4f503a20696e76616c696420676574416d6f756e742072657475726e00000060448201526064016105e9565b602001519050610641565b60006136ec826040518060400160405280601681526020017f4c4f503a2061737365742e63616c6c206661696c6564000000000000000000008152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab578051602014801561370b575060208101516001145b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4c4f503a2061737365742e63616c6c2062616420726573756c7400000000000060448201526064016105e9565b6000610b5361377e612b2d565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052613515908590613edc565b6060831561387e57508161060c565b82511561388e5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e99190615331565b60606004835110613cf15760208301517fffffffff0000000000000000000000000000000000000000000000000000000081167f08c379a00000000000000000000000000000000000000000000000000000000014801561392557506044845110155b15613b265760248481015180860182018051919290919061394790849061512f565b613951919061512f565b865110156139c057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c69642072657665727420726561736f6e0000000000000000000000604482015290519081900360640190fd5b84816040516020018083805190602001908083835b60208310613a1257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016139d5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f4572726f72280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613abf57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613a82565b6001836020036101000a038019825116818451168082178552505050505050905001807f2900000000000000000000000000000000000000000000000000000000000000815250600101925050506040516020818303038152906040529350505050610b53565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f4e487b7100000000000000000000000000000000000000000000000000000000148015613b78575083516024145b15613cef57602484015183613b8c82613fe8565b6040516020018083805190602001908083835b60208310613bdc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b9f565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f50616e6963280000000000000000000000000000000000000000000000000000919093019081528451600690910192850191508083835b60208310613c8957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613c4c565b6001836020036101000a038019825116818451168082178552505050505050905001807f29000000000000000000000000000000000000000000000000000000000000008152506001019250505060405160208183030381529060405292505050610b53565b505b81613cfb8461400e565b6040516020018083805190602001908083835b60208310613d4b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613d0e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527f556e6b6e6f776e28000000000000000000000000000000000000000000000000919093019081528451600890910192850191508083835b60208310613df857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613dbb565b6001836020036101000a038019825116818451168082178552505050505050905001807f290000000000000000000000000000000000000000000000000000000000000081525060010192505050604051602081830303815290604052905092915050565b600080825160411415613e945760208301516040840151606085015160001a613e88878285856142b3565b94509450505050613ec6565b825160401415613ebe5760208301516040840151613eb38683836143cb565b935093505050613ec6565b506000905060025b9250929050565b60606106418484600085614413565b6000613f3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613ecd9092919063ffffffff16565b805190915015612fab5780806020019051810190613f5c9190615344565b612fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105e9565b6060610b5382604051602001808281526020019150506040516020818303038152906040525b80516060907f3031323334353637383961626364656600000000000000000000000000000000906000906140439060026150f2565b61404e90600261512f565b67ffffffffffffffff811115614066576140666145c5565b6040519080825280601f01601f191660200182016040528015614090576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106140c7576140c7615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061412a5761412a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b84518110156142ab5782600486838151811061417a5761417a615199565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c60f81c601081106141b6576141b6615199565b1a60f81b826141c68360026150f2565b6141d190600261512f565b815181106141e1576141e1615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508285828151811061422357614223615199565b60209101015160f81c600f166010811061423f5761423f615199565b1a60f81b8261424f8360026150f2565b61425a90600361512f565b8151811061426a5761426a615199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806142a38161523d565b91505061415c565b509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156142ea57506000905060036143c2565b8460ff16601b1415801561430257508460ff16601c14155b1561431357506000905060046143c2565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614367573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166143bb576000600192509250506143c2565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01614405878288856142b3565b935093505050935093915050565b6060824710156144a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105e9565b843b61450d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e9565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614536919061562c565b60006040518083038185875af1925050503d8060008114614573576040519150601f19603f3d011682016040523d82523d6000602084013e614578565b606091505b509150915061458882828661386f565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f5657600080fd5b80356145c081614593565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101e0810167ffffffffffffffff81118282101715614618576146186145c5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614665576146656145c5565b604052919050565b600082601f83011261467e57600080fd5b813567ffffffffffffffff811115614698576146986145c5565b6146c960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161461e565b8181528460208386010111156146de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561471057600080fd5b83359250602084013561472281614593565b9150604084013567ffffffffffffffff81111561473e57600080fd5b61474a8682870161466d565b9150509250925092565b60008060006060848603121561476957600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561479657600080fd5b84356147a181614593565b935060208501356147b181614593565b93969395505050506040820135916060013590565b600060e082840312156147d857600080fd5b60405160e0810181811067ffffffffffffffff821117156147fb576147fb6145c5565b60405282358152905080602083013561481381614593565b6020820152604083013561482681614593565b6040820152606083013561483981614593565b6060820152608083013561484c81614593565b8060808301525060a083013560a082015260c083013560c08201525092915050565b60008083601f84011261488057600080fd5b50813567ffffffffffffffff81111561489857600080fd5b602083019150836020828501011115613ec657600080fd5b600080600080600080600080610180898b0312156148cd57600080fd5b6148d78a8a6147c6565b975060e089013567ffffffffffffffff808211156148f457600080fd5b6149008c838d0161486e565b90995097506101008b013596506101208b013595506101408b0135915061492682614593565b9093506101608a0135908082111561493d57600080fd5b5061494a8b828c0161486e565b999c989b5096995094979396929594505050565b6000806040838503121561497157600080fd5b823561497c81614593565b946020939093013593505050565b60006101e0828403121561499d57600080fd5b6149a56145f4565b9050813581526149b7602083016145b5565b60208201526149c8604083016145b5565b60408201526149d9606083016145b5565b60608201526149ea608083016145b5565b60808201526149fb60a083016145b5565b60a082015260c082013560c082015260e082013560e08201526101008083013567ffffffffffffffff80821115614a3157600080fd5b614a3d8683870161466d565b83850152610120925082850135915080821115614a5957600080fd5b614a658683870161466d565b83850152610140925082850135915080821115614a8157600080fd5b614a8d8683870161466d565b83850152610160925082850135915080821115614aa957600080fd5b614ab58683870161466d565b83850152610180925082850135915080821115614ad157600080fd5b614add8683870161466d565b838501526101a0925082850135915080821115614af957600080fd5b614b058683870161466d565b838501526101c0925082850135915080821115614b2157600080fd5b50614b2e8582860161466d565b82840152505092915050565b600080600080600080600080600060e08a8c031215614b5857600080fd5b893567ffffffffffffffff80821115614b7057600080fd5b614b7c8d838e0161498a565b9a5060208c0135915080821115614b9257600080fd5b614b9e8d838e0161486e565b909a50985060408c0135975060608c0135965060808c0135955060a08c01359150614bc882614593565b90935060c08b01359080821115614bde57600080fd5b50614beb8c828d0161486e565b915080935050809150509295985092959850929598565b600060208284031215614c1457600080fd5b5035919050565b60008060008060008060a08789031215614c3457600080fd5b863567ffffffffffffffff80821115614c4c57600080fd5b614c588a838b0161498a565b97506020890135915080821115614c6e57600080fd5b50614c7b89828a0161486e565b979a90995096976040810135976060820135975060809091013595509350505050565b600060208284031215614cb057600080fd5b813561060c81614593565b600060208284031215614ccd57600080fd5b813560ff8116811461060c57600080fd5b60008083601f840112614cf057600080fd5b50813567ffffffffffffffff811115614d0857600080fd5b6020830191508360208260051b8501011115613ec657600080fd5b60008060008060408587031215614d3957600080fd5b843567ffffffffffffffff80821115614d5157600080fd5b614d5d88838901614cde565b90965094506020870135915080821115614d7657600080fd5b50614d8387828801614cde565b95989497509550505050565b60006020808385031215614da257600080fd5b823567ffffffffffffffff80821115614dba57600080fd5b818501915085601f830112614dce57600080fd5b813581811115614de057614de06145c5565b8060051b9150614df184830161461e565b8181529183018401918481019088841115614e0b57600080fd5b938501935b8385101561328857843582529385019390850190614e10565b6020808252825182820181905260009190848201906040850190845b81811015614e6157835183529284019291840191600101614e45565b50909695505050505050565b600060208284031215614e7f57600080fd5b813567ffffffffffffffff811115614e9657600080fd5b6106418482850161498a565b600080600080600080600060c0888a031215614ebd57600080fd5b873567ffffffffffffffff80821115614ed557600080fd5b614ee18b838c0161498a565b985060208a0135915080821115614ef757600080fd5b50614f048a828b0161486e565b90975095505060408801359350606088013592506080880135915060a0880135614f2d81614593565b8091505092959891949750929550565b6000806000806000806101608789031215614f5757600080fd5b614f6188886147c6565b955060e087013567ffffffffffffffff811115614f7d57600080fd5b614f8989828a0161486e565b90965094505061010087013592506101208701359150610140870135614fae81614593565b809150509295509295509295565b60008060408385031215614fcf57600080fd5b8235614fda81614593565b9150602083013567ffffffffffffffff811115614ff657600080fd5b6150028582860161466d565b9150509250929050565b60008060006060848603121561502157600080fd5b833561502c81614593565b95602085013595506040909401359392505050565b6000806000806000610140868803121561505a57600080fd5b61506487876147c6565b945060e086013567ffffffffffffffff81111561508057600080fd5b61508c8882890161486e565b96999098509596610100810135966101209091013595509350505050565b6000602082840312156150bc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561512a5761512a6150c3565b500290565b60008219821115615142576151426150c3565b500190565b600082821015615159576151596150c3565b500390565b600082615194577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126151fd57600080fd5b83018035915067ffffffffffffffff82111561521857600080fd5b602001915036819003821315613ec657600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561526f5761526f6150c3565b5060010190565b60005b83811015615291578181015183820152602001615279565b838111156135155750506000910152565b7f43414c4c5f524553554c54535f000000000000000000000000000000000000008152600082516152da81600d850160208701615276565b91909101600d0192915050565b600081518084526152ff816020860160208601615276565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061060c60208301846152e7565b60006020828403121561535657600080fd5b8151801515811461060c57600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000086168152846004820152836024820152826044820152600082516153b2816064850160208701615276565b919091016064019695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015280871660408401525084606083015283608083015260c060a083015261328860c08301846152e7565b600181815b8085111561546957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561544f5761544f6150c3565b8085161561545c57918102915b93841c9390800290615415565b509250929050565b60008261548057506001610b53565b8161548d57506000610b53565b81600181146154a357600281146154ad576154c9565b6001915050610b53565b60ff8411156154be576154be6150c3565b50506001821b610b53565b5060208310610133831016604e8410600b84101617156154ec575081810a610b53565b6154f68383615410565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615528576155286150c3565b029392505050565b600061060c60ff841683615471565b6000610200820190508a82528951602083015260208a015173ffffffffffffffffffffffffffffffffffffffff80821660408501528060408d01511660608501528060608d0151166080850152505060808a01516155b560a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08a015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08a015160e083015260e08a015161010083015288610120830152876101408301528661016083015285610180830152846101a0830152836101c0830152826101e08301529a9950505050505050505050565b6000825161563e818460208701615276565b9190910192915050565b6000808585111561565857600080fd5b8386111561566557600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061064160408301846152e7565b6000602082840312156156cc57600080fd5b81517fffffffff000000000000000000000000000000000000000000000000000000008116811461060c57600080fd5b6000835161570e818460208801615276565b919091019182525060200191905056fea264697066735822122009df7b6648e6254c8e6876e6c4e990013e2c23656cf75059f424ad6b65c794cd64736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.48072 | 3,204.4133 | $1,540.43 |
[ 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.