Source Code
Overview
S Balance
S Value
$0.00Latest 25 from a total of 250 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Try Multicall | 60916780 | 4 days ago | IN | 0 S | 0.00612392 | ||||
| Try Multicall | 59911570 | 18 days ago | IN | 0 S | 0.00572698 | ||||
| Try Multicall | 59769973 | 19 days ago | IN | 0 S | 0.00572566 | ||||
| Multicall And Bu... | 59402785 | 24 days ago | IN | 33.51135447 S | 0.00740834 | ||||
| Multicall And Bu... | 59402781 | 24 days ago | IN | 33.70474547 S | 0.00740901 | ||||
| Multicall And Bu... | 59402777 | 24 days ago | IN | 0 S | 0.00691273 | ||||
| Multicall And Bu... | 59402773 | 24 days ago | IN | 0 S | 0.00691133 | ||||
| Multicall And Bu... | 59402766 | 24 days ago | IN | 0 S | 0.00696584 | ||||
| Multicall And Bu... | 59402762 | 24 days ago | IN | 33.69438677 S | 0.00739866 | ||||
| Multicall And Bu... | 59402755 | 24 days ago | IN | 134.25502769 S | 0.00739951 | ||||
| Multicall And Bu... | 59402751 | 24 days ago | IN | 0 S | 0.0069624 | ||||
| Multicall And Bu... | 59402745 | 24 days ago | IN | 33.8642089 S | 0.00745154 | ||||
| Multicall And Bu... | 59402738 | 24 days ago | IN | 33.87763253 S | 0.00740175 | ||||
| Try Multicall | 58266460 | 39 days ago | IN | 0 S | 0.0035074 | ||||
| Try Multicall | 57679502 | 46 days ago | IN | 0 S | 0.00331985 | ||||
| Try Multicall | 57515778 | 48 days ago | IN | 0 S | 0.03184637 | ||||
| Try Multicall | 57515778 | 48 days ago | IN | 0 S | 0.03179748 | ||||
| Try Multicall | 57515776 | 48 days ago | IN | 0 S | 0.03949841 | ||||
| Try Multicall | 57515776 | 48 days ago | IN | 0 S | 0.03964592 | ||||
| Try Multicall | 57515774 | 48 days ago | IN | 0 S | 0.03958916 | ||||
| Try Multicall | 57515774 | 48 days ago | IN | 0 S | 0.03185721 | ||||
| Try Multicall | 57515774 | 48 days ago | IN | 0 S | 0.0394917 | ||||
| Try Multicall | 57515773 | 48 days ago | IN | 0 S | 0.03950226 | ||||
| Try Multicall | 57515250 | 48 days ago | IN | 0 S | 0.00637664 | ||||
| Try Multicall | 57514961 | 48 days ago | IN | 0 S | 0.00538345 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 59402785 | 24 days ago | 33.51135447 S | ||||
| 59402781 | 24 days ago | 33.70474547 S | ||||
| 59402762 | 24 days ago | 33.69438677 S | ||||
| 59402755 | 24 days ago | 134.25502769 S | ||||
| 59402745 | 24 days ago | 33.8642089 S | ||||
| 59402738 | 24 days ago | 33.87763253 S | ||||
| 50093635 | 107 days ago | 3.3707613 S | ||||
| 50093616 | 107 days ago | 2.57745587 S | ||||
| 50093587 | 107 days ago | 3.80826479 S | ||||
| 50093566 | 107 days ago | 3.79997024 S | ||||
| 50093558 | 107 days ago | 3.84623883 S | ||||
| 39447183 | 189 days ago | 13.38235294 S | ||||
| 39447170 | 189 days ago | 1.81553482 S | ||||
| 39447146 | 189 days ago | 4.57263493 S | ||||
| 39447126 | 189 days ago | 5.75274595 S | ||||
| 39447121 | 189 days ago | 5.75294808 S | ||||
| 22941947 | 272 days ago | 2.66750045 S | ||||
| 22941896 | 272 days ago | 0.95491118 S | ||||
| 22941886 | 272 days ago | 28.88321923 S | ||||
| 22941866 | 272 days ago | 0.79964384 S | ||||
| 22941852 | 272 days ago | 0.87385677 S | ||||
| 15671353 | 308 days ago | 10.8393 S | ||||
| 14449580 | 314 days ago | 160.18 S | ||||
| 10135508 | 334 days ago | 14.4524 S | ||||
| 6036704 | 360 days ago | 229.42392088 S |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Api3MarketV2
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../access/HashRegistry.sol"; import "../utils/ExtendedSelfMulticall.sol"; import "./interfaces/IApi3MarketV2.sol"; import "../vendor/@openzeppelin/[email protected]/utils/math/SafeCast.sol"; import "../vendor/@openzeppelin/[email protected]/utils/cryptography/MerkleProof.sol"; import "./interfaces/IApi3ServerV1.sol"; import "./interfaces/IApi3ServerV1OevExtension.sol"; import "./proxies/interfaces/IApi3ReaderProxyV1Factory.sol"; import "./interfaces/IAirseekerRegistry.sol"; /// @title The contract that API3 users interact with using the API3 Market /// frontend to purchase data feed subscriptions /// @notice API3 streamlines and protocolizes its integration processes through /// the API3 Market (https://market.api3.org), which is a data feed /// subscription marketplace. The Api3MarketV2 contract is the on-chain portion /// of this system. /// Api3MarketV2 enables API3 to predetermine the decisions related to its data /// feed services (such as the curation of data feed sources or subscription /// prices) and publish them on-chain. This streamlines the intergation flow, /// as it allows the users to initiate subscriptions immediately, without /// requiring any two-way communication with API3. Furthermore, this removes /// the need for API3 to have agents operating in the meatspace gathering order /// details, quoting prices and reviewing payments, and allows all such /// operations to be cryptographically secured with a multi-party scheme in an /// end-to-end manner. /// @dev The user is strongly recommended to use the API3 Market frontend while /// interacting with this contract, mostly because doing so successfully /// requires some amount of knowledge of other API3 contracts. Specifically, /// Api3MarketV2 requires the data feed for which the subscription is being /// purchased to be "readied", the correct Merkle proofs to be provided, and /// enough payment to be made. The API3 Market frontend will fetch the /// appropriate Merkle proofs, create a multicall transaction that will ready /// the data feed before making the call to buy the subscription, and compute /// the amount to be sent that will barely allow the subscription to be /// purchased. For most users, building such a transaction themselves would be /// impractical. contract Api3MarketV2 is HashRegistry, ExtendedSelfMulticall, IApi3MarketV2 { enum UpdateParametersComparisonResult { EqualToQueued, BetterThanQueued, WorseThanQueued } // The update parameters for each subscription is kept in a hash map rather // than in full form as an optimization. Refer to AirseekerRegistry for a // similar scheme. // The subscription queues are kept as linked lists, for which each // subscription has a next subscription ID field. struct Subscription { bytes32 updateParametersHash; uint32 endTimestamp; uint224 dailyPrice; bytes32 nextSubscriptionId; } /// @notice dAPI management Merkle root hash type /// @dev "Hash type" is what HashRegistry uses to address hashes used for /// different purposes bytes32 public constant override DAPI_MANAGEMENT_MERKLE_ROOT_HASH_TYPE = keccak256(abi.encodePacked("dAPI management Merkle root")); /// @notice dAPI pricing Merkle root hash type bytes32 public constant override DAPI_PRICING_MERKLE_ROOT_HASH_TYPE = keccak256(abi.encodePacked("dAPI pricing Merkle root")); /// @notice Signed API URL Merkle root hash type bytes32 public constant override SIGNED_API_URL_MERKLE_ROOT_HASH_TYPE = keccak256(abi.encodePacked("Signed API URL Merkle root")); /// @notice Maximum dAPI update age. This contract cannot be used to set a /// dAPI name to a data feed that has not been updated in the last /// `MAXIMUM_DAPI_UPDATE_AGE`. uint256 public constant override MAXIMUM_DAPI_UPDATE_AGE = 1 days; /// @notice Api3ServerV1 contract address address public immutable override api3ServerV1; /// @notice Api3ReaderProxyV1Factory contract address address public immutable override api3ReaderProxyV1Factory; /// @notice AirseekerRegistry contract address address public override airseekerRegistry; /// @notice Maximum subscription queue length for a dAPI /// @dev Some functionality in this contract requires to iterate through /// the entire subscription queue for a dAPI, and the queue length is /// limited to prevent this process from being bloated. Considering that /// each item in the subscription queue has unique update parameters, the /// length of the subscription queue is also limited by the number of /// unique update parameters offered in the dAPI pricing Merkle tree. For /// reference, at the time this contract is implemented, the API3 Market /// offers 4 update parameter options. uint256 public immutable override maximumSubscriptionQueueLength; /// @notice Subscriptions indexed by their IDs mapping(bytes32 => Subscription) public override subscriptions; /// @notice dAPI name to current subscription ID, which denotes the start /// of the subscription queue for the dAPI mapping(bytes32 => bytes32) public override dapiNameToCurrentSubscriptionId; // Update parameters hash map mapping(bytes32 => bytes) private updateParametersHashToValue; // Length of abi.encode(address, bytes32) uint256 private constant DATA_FEED_DETAILS_LENGTH_FOR_SINGLE_BEACON = 32 + 32; // Length of abi.encode(uint256, int224, uint256) uint256 private constant UPDATE_PARAMETERS_LENGTH = 32 + 32 + 32; bytes32 private constant API3MARKETV2_SIGNATURE_DELEGATION_HASH_TYPE = keccak256(abi.encodePacked("Api3MarketV2 signature delegation")); /// @dev The maximum subscription queue length should be large enough to /// not obstruct subscription purchases under usual conditions, and small /// enough to keep the queue at an iterable size. For example, if the /// number of unique update parameters in the dAPI pricing Merkle trees /// that are being used is around 5, a maximum subscription queue length of /// 10 would be acceptable for a chain with typical gas costs. /// @param owner_ Owner address /// @param api3ReaderProxyV1Factory_ Api3ReaderProxyV1Factory contract /// address /// @param maximumSubscriptionQueueLength_ Maximum subscription queue /// length constructor( address owner_, address api3ReaderProxyV1Factory_, uint256 maximumSubscriptionQueueLength_ ) HashRegistry(owner_) { require( maximumSubscriptionQueueLength_ != 0, "Maximum queue length zero" ); api3ReaderProxyV1Factory = api3ReaderProxyV1Factory_; api3ServerV1 = IApi3ServerV1OevExtension( IApi3ReaderProxyV1Factory(api3ReaderProxyV1Factory_) .api3ServerV1OevExtension() ).api3ServerV1(); maximumSubscriptionQueueLength = maximumSubscriptionQueueLength_; } /// @notice Returns the owner address /// @return Owner address function owner() public view override(HashRegistry, IOwnable) returns (address) { return super.owner(); } /// @notice Overriden to be disabled function renounceOwnership() public pure override(HashRegistry, IOwnable) { revert("Ownership cannot be renounced"); } /// @notice Overriden to be disabled function transferOwnership( address ) public pure override(HashRegistry, IOwnable) { revert("Ownership cannot be transferred"); } /// @notice Called once by the owner to set the AirseekerRegistry address /// @dev There is a circular dependency between an Api3MarketV2 and its /// respective AirseekerRegistry. In a previous implementation, /// Api3Market deployed its AirseekerRegistry in its constructor, yet the /// resulting deployment transaction required too much gas, which ended up /// being an issue on some chains. Instead, the current deployment flow is /// for Api3MarketV2 to be deployed with a transaction, AirseekerRegistry /// to be deployed with another transaction with the Api3MarketV2 address /// as an argument, and finally, for the Api3MarketV2 owner to set the /// AirseekerRegister address with a third transaction. /// Once the AirseekerRegister address is set, it cannot be updated. /// @param airseekerRegistry_ AirseekerRegistry address function setAirseekerRegistry( address airseekerRegistry_ ) external override onlyOwner { require( airseekerRegistry_ != address(0), "AirseekerRegistry address zero" ); require( airseekerRegistry == address(0), "AirseekerRegistry already set" ); // The following check does not guarantee that `airseekerRegistry_` // belongs to a valid AirseekerRegistry instance. The Api3MarketV2 // owner is responsible with verifying that it is before calling this // function. require( IAirseekerRegistry(airseekerRegistry_).owner() == address(this), "Not AirseekerRegistry owner" ); airseekerRegistry = airseekerRegistry_; emit SetAirseekerRegistry(airseekerRegistry_); } /// @notice Buys subscription and updates the current subscription ID if /// necessary. The user is recommended to interact with this contract over /// the API3 Market frontend due to its complexity. /// @dev The data feed that the dAPI name will be set to after this /// function is called must be readied (see `validateDataFeedReadiness()`) /// before calling this function. /// Enough funds must be sent to put the sponsor wallet balance over its /// expected amount after the subscription is bought. Since sponsor wallets /// send data feed update transactions, it is not possible to determine /// what their balance will be at the time sent transactions are confirmed. /// To avoid transactions being reverted as a result of this, consider /// sending some extra. /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param sponsorWallet Sponsor wallet address /// @param updateParameters Update parameters /// @param duration Subscription duration /// @param price Subscription price /// @param dapiManagementAndDapiPricingMerkleData ABI-encoded dAPI /// management and dAPI pricing Merkle roots and proofs /// @return subscriptionId Subscription ID function buySubscription( bytes32 dapiName, bytes32 dataFeedId, address payable sponsorWallet, bytes calldata updateParameters, uint256 duration, uint256 price, bytes calldata dapiManagementAndDapiPricingMerkleData ) public payable override returns (bytes32 subscriptionId) { require(dataFeedId != bytes32(0), "Data feed ID zero"); require(sponsorWallet != address(0), "Sponsor wallet address zero"); verifyDapiManagementAndDapiPricingMerkleProofs( dapiName, dataFeedId, sponsorWallet, updateParameters, duration, price, dapiManagementAndDapiPricingMerkleData ); subscriptionId = addSubscriptionToQueue( dapiName, dataFeedId, updateParameters, duration, price ); require( sponsorWallet.balance + msg.value >= computeExpectedSponsorWalletBalance(dapiName), "Insufficient payment" ); emit BoughtSubscription( dapiName, subscriptionId, dataFeedId, sponsorWallet, updateParameters, duration, price, msg.value ); if (msg.value > 0) { (bool success, ) = sponsorWallet.call{value: msg.value}(""); require(success, "Transfer unsuccessful"); } } /// @notice Called by the owner to cancel all subscriptions for a dAPI /// that needs to be decommissioned urgently /// @dev The root of a new dAPI pricing Merkle tree that excludes the dAPI /// should be registered before canceling the subscriptions. Otherwise, /// anyone can immediately buy the subscriptions again. /// @param dapiName dAPI name function cancelSubscriptions(bytes32 dapiName) external override onlyOwner { require( dapiNameToCurrentSubscriptionId[dapiName] != bytes32(0), "Subscription queue empty" ); dapiNameToCurrentSubscriptionId[dapiName] = bytes32(0); IAirseekerRegistry(airseekerRegistry).setDapiNameToBeDeactivated( dapiName ); emit CanceledSubscriptions(dapiName); } /// @notice If the current subscription has ended, updates it with the one /// that will end next /// @dev The fact that there is a current subscription that has ended would /// mean that API3 is providing a service that was not paid for. Therefore, /// API3 should poll this function for all active dAPI names and call it /// whenever it is not going to revert to downgrade the specs. /// @param dapiName dAPI name function updateCurrentSubscriptionId(bytes32 dapiName) public override { bytes32 currentSubscriptionId = dapiNameToCurrentSubscriptionId[ dapiName ]; require( currentSubscriptionId != bytes32(0), "Subscription queue empty" ); require( subscriptions[currentSubscriptionId].endTimestamp <= block.timestamp, "Current subscription not ended" ); updateEndedCurrentSubscriptionId(dapiName, currentSubscriptionId); } /// @notice Updates the dAPI name to match the respective Merkle leaf /// @dev Buying a dAPI subscription always updates the dAPI name if /// necessary. However, API3 may also publish new Merkle roots between /// subscription purchases, in which case API3 should call this function to /// bring the chain state up to date. Therefore, API3 should poll this /// function for all active dAPI names and call it whenever it will not /// revert. /// Similar to `buySubscription()`, this function requires the data feed /// that the dAPI will be pointed to to be readied. /// This function is allowed to be called even when the respective dAPI is /// not active, which means that a dAPI name being set does not imply that /// the respective data feed is in service. Users should only use dAPIs for /// which there is an active subscription with update parameters that /// satisfy their needs. /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param sponsorWallet Sponsor wallet address /// @param dapiManagementMerkleData ABI-encoded dAPI management Merkle root /// and proof function updateDapiName( bytes32 dapiName, bytes32 dataFeedId, address sponsorWallet, bytes calldata dapiManagementMerkleData ) external override { if (dataFeedId != bytes32(0)) { require(sponsorWallet != address(0), "Sponsor wallet address zero"); } else { require( sponsorWallet == address(0), "Sponsor wallet address not zero" ); } verifyDapiManagementMerkleProof( dapiName, dataFeedId, sponsorWallet, dapiManagementMerkleData ); bytes32 currentDataFeedId = IApi3ServerV1(api3ServerV1) .dapiNameHashToDataFeedId(keccak256(abi.encodePacked(dapiName))); require(currentDataFeedId != dataFeedId, "Does not update dAPI name"); if (dataFeedId != bytes32(0)) { validateDataFeedReadiness(dataFeedId); } IApi3ServerV1(api3ServerV1).setDapiName(dapiName, dataFeedId); } /// @notice Updates the signed API URL of the Airnode to match the /// respective Merkle leaf /// @dev Unlike the dAPI management and pricing Merkle leaves, the signed /// API URL Merkle leaves are not registered by the users as a part of /// subscription purchase transactions. API3 should poll this function for /// all Airnodes that are used in active dAPIs and call it whenever it will /// not revert. /// @param airnode Airnode address /// @param signedApiUrl Signed API URL /// @param signedApiUrlMerkleData ABI-encoded signed API URL Merkle root /// and proof function updateSignedApiUrl( address airnode, string calldata signedApiUrl, bytes calldata signedApiUrlMerkleData ) external override { verifySignedApiUrlMerkleProof( airnode, signedApiUrl, signedApiUrlMerkleData ); require( keccak256(abi.encodePacked(signedApiUrl)) != keccak256( abi.encodePacked( IAirseekerRegistry(airseekerRegistry) .airnodeToSignedApiUrl(airnode) ) ), "Does not update signed API URL" ); IAirseekerRegistry(airseekerRegistry).setSignedApiUrl( airnode, signedApiUrl ); } /// @notice Multi-calls this contract, followed by a call with value to buy /// the subscription /// @dev This function is for the API3 Market frontend to call /// `eth_estimateGas` on a single transaction that readies a data feed and /// buys the respective subscription /// @param multicallData Array of calldata of batched calls /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param sponsorWallet Sponsor wallet address /// @param updateParameters Update parameters /// @param duration Subscription duration /// @param price Subscription price /// @param dapiManagementAndDapiPricingMerkleData ABI-encoded dAPI /// management and dAPI pricing Merkle roots and proofs /// @return returndata Array of returndata of batched calls /// @return subscriptionId Subscription ID function multicallAndBuySubscription( bytes[] calldata multicallData, bytes32 dapiName, bytes32 dataFeedId, address payable sponsorWallet, bytes calldata updateParameters, uint256 duration, uint256 price, bytes calldata dapiManagementAndDapiPricingMerkleData ) external payable override returns (bytes[] memory returndata, bytes32 subscriptionId) { returndata = this.multicall(multicallData); subscriptionId = buySubscription( dapiName, dataFeedId, sponsorWallet, updateParameters, duration, price, dapiManagementAndDapiPricingMerkleData ); } /// @notice Multi-calls this contract in a way that the transaction does /// not revert if any of the batched calls reverts, followed by a call with /// value to buy the subscription /// @dev This function is for the API3 Market frontend to send a single /// transaction that readies a data feed and buys the respective /// subscription. `tryMulticall()` is preferred in the purchase transaction /// because the readying calls may revert due to race conditions. /// @param tryMulticallData Array of calldata of batched calls /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param sponsorWallet Sponsor wallet address /// @param updateParameters Update parameters /// @param duration Subscription duration /// @param price Subscription price /// @param dapiManagementAndDapiPricingMerkleData ABI-encoded dAPI /// management and dAPI pricing Merkle roots and proofs /// @return successes Array of success conditions of batched calls /// @return returndata Array of returndata of batched calls /// @return subscriptionId Subscription ID function tryMulticallAndBuySubscription( bytes[] calldata tryMulticallData, bytes32 dapiName, bytes32 dataFeedId, address payable sponsorWallet, bytes calldata updateParameters, uint256 duration, uint256 price, bytes calldata dapiManagementAndDapiPricingMerkleData ) external payable override returns ( bool[] memory successes, bytes[] memory returndata, bytes32 subscriptionId ) { (successes, returndata) = this.tryMulticall(tryMulticallData); subscriptionId = buySubscription( dapiName, dataFeedId, sponsorWallet, updateParameters, duration, price, dapiManagementAndDapiPricingMerkleData ); } /// @notice Calls Api3ServerV1 to update the Beacon using data signed by /// the Airnode /// @dev The user is intended to make a multicall transaction through the /// API3 Market frontend to satisfy the required conditions to be able to /// buy a subscription and buy the subscription in a single transaction. /// The functions to which external calls must be made to to satisfy said /// conditions (such as this one) are added to this contract so that they /// can be multi-called by the user. /// @param airnode Airnode address /// @param templateId Template ID /// @param timestamp Signature timestamp /// @param data Update data (an `int256` encoded in contract ABI) /// @param signature Template ID, timestamp and the update data signed by /// the Airnode /// @return beaconId Updated Beacon ID function updateBeaconWithSignedData( address airnode, bytes32 templateId, uint256 timestamp, bytes calldata data, bytes calldata signature ) external override returns (bytes32 beaconId) { return IApi3ServerV1(api3ServerV1).updateBeaconWithSignedData( airnode, templateId, timestamp, data, signature ); } /// @notice Calls Api3ServerV1 to update the Beacon set using the current /// values of its Beacons /// @param beaconIds Beacon IDs /// @return beaconSetId Updated Beacon set ID function updateBeaconSetWithBeacons( bytes32[] calldata beaconIds ) external override returns (bytes32 beaconSetId) { return IApi3ServerV1(api3ServerV1).updateBeaconSetWithBeacons(beaconIds); } /// @notice Calls Api3ReaderProxyV1Factory to deterministically deploy an /// Api3ReaderProxyV1 /// @dev It is recommended for the users to read data feeds through proxies /// deployed by Api3ReaderProxyV1Factory, rather than calling the /// underlying contracts directly. /// Even though proxy deployment is not a condition for purchasing /// subscriptions, the interface is implemented here to allow the user to /// purchase a dAPI subscription and deploy the respective proxy in the /// same transaction with a multicall. /// @param dapiName dAPI name /// @param dappId dApp ID /// @param metadata Metadata associated with the proxy /// @return api3ReaderProxyV1 Api3ReaderProxyV1 address function deployApi3ReaderProxyV1( bytes32 dapiName, uint256 dappId, bytes calldata metadata ) external override returns (address api3ReaderProxyV1) { api3ReaderProxyV1 = IApi3ReaderProxyV1Factory(api3ReaderProxyV1Factory) .deployApi3ReaderProxyV1(dapiName, dappId, metadata); } /// @notice Calls AirseekerRegistry to register the data feed /// @param dataFeedDetails Data feed details /// @return dataFeedId Data feed ID function registerDataFeed( bytes calldata dataFeedDetails ) external override returns (bytes32 dataFeedId) { dataFeedId = IAirseekerRegistry(airseekerRegistry).registerDataFeed( dataFeedDetails ); } /// @notice Computes the expected sponsor wallet balance based on the /// current subscription queue /// @dev API3 estimates the transaction fee cost of subscriptions, and /// prices them accordingly. The subscription fees paid for a dAPI are sent /// to the respective sponsor wallet, which will send the update /// transactions. In the case that a subscription is overpriced, the extra /// funds are automatically rolled over as a discount to the next /// subscription bought for the same dAPI. In the case that a subscription /// is underpriced, there is a risk of the sponsor wallet running out of /// funds, resulting in the subscription specs to not be met. To avoid /// this, API3 should poll this function for all active dAPI names, check /// the respective sponsor wallet balances, and top up the sponsor wallets /// as necessary. The conditions that result in the underpricing will most /// likely require an updated dAPI pricing Merkle root to be published. /// @param dapiName dAPI name /// @return expectedSponsorWalletBalance Expected sponsor wallet balance function computeExpectedSponsorWalletBalance( bytes32 dapiName ) public view override returns (uint256 expectedSponsorWalletBalance) { uint32 startTimestamp = SafeCast.toUint32(block.timestamp); Subscription storage queuedSubscription; for ( bytes32 queuedSubscriptionId = dapiNameToCurrentSubscriptionId[ dapiName ]; queuedSubscriptionId != bytes32(0); queuedSubscriptionId = queuedSubscription.nextSubscriptionId ) { queuedSubscription = subscriptions[queuedSubscriptionId]; uint32 endTimestamp = queuedSubscription.endTimestamp; if (endTimestamp > block.timestamp) { expectedSponsorWalletBalance += ((endTimestamp - startTimestamp) * queuedSubscription.dailyPrice) / 1 days; startTimestamp = endTimestamp; } } } /// @notice Computes the expected sponsor wallet balance after the /// respective subscription is added to the queue /// @dev This function is intended to be used by the API3 Market frontend /// to calculate how much the user should pay to purchase a specific /// subscription. As mentioned in the `buySubscription()` docstring, the /// user should aim for the sponsor wallet balance to be slightly more than /// the required amount in case it sends a transaction in the meantime, /// whose gas cost may decrease the sponsor wallet balance unexpectedly. /// Unit prices of the queued subscriptions are recorded on a daily basis /// and the expected balance is computed from these, which introduces a /// rounding error in the order of Weis. This also applies in practice (in /// that one can buy a subscription whose price is 1 ETH at 0.999... ETH). /// This behavior is accepted due to its effect being negligible. /// @param dapiName dAPI name /// @param updateParameters Update parameters /// @param duration Subscription duration /// @param price Subscription price /// @return expectedSponsorWalletBalance Expected sponsor wallet balance function computeExpectedSponsorWalletBalanceAfterSubscriptionIsAdded( bytes32 dapiName, bytes calldata updateParameters, uint256 duration, uint256 price ) external view override returns (uint256 expectedSponsorWalletBalance) { require( updateParameters.length == UPDATE_PARAMETERS_LENGTH, "Update parameters length invalid" ); ( bytes32 subscriptionId, uint32 endTimestamp, bytes32 previousSubscriptionId, bytes32 nextSubscriptionId ) = prospectSubscriptionPositionInQueue( dapiName, updateParameters, duration ); uint256 dailyPrice = (price * 1 days) / duration; uint32 startTimestamp = SafeCast.toUint32(block.timestamp); bytes32 queuedSubscriptionId = previousSubscriptionId == bytes32(0) ? subscriptionId : dapiNameToCurrentSubscriptionId[dapiName]; for (; queuedSubscriptionId != bytes32(0); ) { if (queuedSubscriptionId == subscriptionId) { expectedSponsorWalletBalance += ((endTimestamp - startTimestamp) * dailyPrice) / 1 days; startTimestamp = endTimestamp; queuedSubscriptionId = nextSubscriptionId; } else { Subscription storage queuedSubscription = subscriptions[ queuedSubscriptionId ]; uint32 queuedSubscriptionEndTimestamp = queuedSubscription .endTimestamp; if (queuedSubscriptionEndTimestamp > block.timestamp) { expectedSponsorWalletBalance += ((queuedSubscriptionEndTimestamp - startTimestamp) * queuedSubscription.dailyPrice) / 1 days; startTimestamp = queuedSubscriptionEndTimestamp; } if (previousSubscriptionId == queuedSubscriptionId) { queuedSubscriptionId = subscriptionId; } else { queuedSubscriptionId = queuedSubscription .nextSubscriptionId; } } } } /// @notice Gets all data about the dAPI that is available /// @dev This function is intended to be used by the API3 Market frontend /// to get all data related to a specific dAPI. It returns the entire /// subscription queue, including the items whose end timestamps are in the /// past. /// @param dapiName dAPI name /// @return dataFeedDetails Data feed details /// @return dapiValue dAPI value read from Api3ServerV1 /// @return dapiTimestamp dAPI timestamp read from Api3ServerV1 /// @return beaconValues Beacon values read from Api3ServerV1 /// @return beaconTimestamps Beacon timestamps read from Api3ServerV1 /// @return updateParameters Update parameters of the subscriptions in the /// queue /// @return endTimestamps End timestamps of the subscriptions in the queue /// @return dailyPrices Daily prices of the subscriptions in the queue function getDapiData( bytes32 dapiName ) external view override returns ( bytes memory dataFeedDetails, int224 dapiValue, uint32 dapiTimestamp, int224[] memory beaconValues, uint32[] memory beaconTimestamps, bytes[] memory updateParameters, uint32[] memory endTimestamps, uint224[] memory dailyPrices ) { bytes32 currentDataFeedId = IApi3ServerV1(api3ServerV1) .dapiNameHashToDataFeedId(keccak256(abi.encodePacked(dapiName))); ( dataFeedDetails, dapiValue, dapiTimestamp, beaconValues, beaconTimestamps ) = getDataFeedData(currentDataFeedId); uint256 queueLength = 0; for ( bytes32 queuedSubscriptionId = dapiNameToCurrentSubscriptionId[ dapiName ]; queuedSubscriptionId != bytes32(0); queuedSubscriptionId = subscriptions[queuedSubscriptionId] .nextSubscriptionId ) { queueLength++; } updateParameters = new bytes[](queueLength); endTimestamps = new uint32[](queueLength); dailyPrices = new uint224[](queueLength); Subscription storage queuedSubscription = subscriptions[ dapiNameToCurrentSubscriptionId[dapiName] ]; for (uint256 ind = 0; ind < queueLength; ind++) { updateParameters[ind] = updateParametersHashToValue[ queuedSubscription.updateParametersHash ]; endTimestamps[ind] = queuedSubscription.endTimestamp; dailyPrices[ind] = queuedSubscription.dailyPrice; queuedSubscription = subscriptions[ queuedSubscription.nextSubscriptionId ]; } } /// @notice Gets all data about the data feed that is available /// @dev This function is intended to be used by the API3 Market frontend /// to determine what needs to be done to ready the data feed to purchase /// the respective subscription. /// In the case that the client wants to use this to fetch the respective /// Beacon readings for an unregistered data feed, they can do a static /// multicall where the `getDataFeedData()` call is preceded by a /// `registerDataFeed()` call. /// @param dataFeedId Data feed ID /// @return dataFeedDetails Data feed details /// @return dataFeedValue Data feed value read from Api3ServerV1 /// @return dataFeedTimestamp Data feed timestamp read from Api3ServerV1 /// @return beaconValues Beacon values read from Api3ServerV1 /// @return beaconTimestamps Beacon timestamps read from Api3ServerV1 function getDataFeedData( bytes32 dataFeedId ) public view returns ( bytes memory dataFeedDetails, int224 dataFeedValue, uint32 dataFeedTimestamp, int224[] memory beaconValues, uint32[] memory beaconTimestamps ) { dataFeedDetails = IAirseekerRegistry(airseekerRegistry) .dataFeedIdToDetails(dataFeedId); (dataFeedValue, dataFeedTimestamp) = IApi3ServerV1(api3ServerV1) .dataFeeds(dataFeedId); if ( dataFeedDetails.length == DATA_FEED_DETAILS_LENGTH_FOR_SINGLE_BEACON ) { beaconValues = new int224[](1); beaconTimestamps = new uint32[](1); (address airnode, bytes32 templateId) = abi.decode( dataFeedDetails, (address, bytes32) ); (beaconValues[0], beaconTimestamps[0]) = IApi3ServerV1(api3ServerV1) .dataFeeds(deriveBeaconId(airnode, templateId)); } else if (dataFeedDetails.length != 0) { (address[] memory airnodes, bytes32[] memory templateIds) = abi .decode(dataFeedDetails, (address[], bytes32[])); uint256 beaconCount = airnodes.length; beaconValues = new int224[](beaconCount); beaconTimestamps = new uint32[](beaconCount); for (uint256 ind = 0; ind < beaconCount; ind++) { (beaconValues[ind], beaconTimestamps[ind]) = IApi3ServerV1( api3ServerV1 ).dataFeeds(deriveBeaconId(airnodes[ind], templateIds[ind])); } } } /// @notice Subscription ID to update parameters /// @param subscriptionId Subscription ID /// @return updateParameters Update parameters function subscriptionIdToUpdateParameters( bytes32 subscriptionId ) public view override returns (bytes memory updateParameters) { updateParameters = updateParametersHashToValue[ subscriptions[subscriptionId].updateParametersHash ]; } /// @notice Returns the signature delegation hash type used in delegation /// signatures /// @return Signature delegation hash type function signatureDelegationHashType() public view virtual override(HashRegistry, IHashRegistry) returns (bytes32) { return API3MARKETV2_SIGNATURE_DELEGATION_HASH_TYPE; } /// @notice Adds the subscription to the queue if applicable /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param updateParameters Update parameters /// @param duration Subscription duration /// @param price Subscription price function addSubscriptionToQueue( bytes32 dapiName, bytes32 dataFeedId, bytes calldata updateParameters, uint256 duration, uint256 price ) internal returns (bytes32 subscriptionId) { uint32 endTimestamp; bytes32 previousSubscriptionId; bytes32 nextSubscriptionId; ( subscriptionId, endTimestamp, previousSubscriptionId, nextSubscriptionId ) = prospectSubscriptionPositionInQueue( dapiName, updateParameters, duration ); bytes32 updateParametersHash = keccak256(updateParameters); if (updateParametersHashToValue[updateParametersHash].length == 0) { updateParametersHashToValue[ updateParametersHash ] = updateParameters; } subscriptions[subscriptionId] = Subscription({ updateParametersHash: updateParametersHash, endTimestamp: endTimestamp, dailyPrice: SafeCast.toUint224((price * 1 days) / duration), nextSubscriptionId: nextSubscriptionId }); if (previousSubscriptionId == bytes32(0)) { if (subscriptionId != dapiNameToCurrentSubscriptionId[dapiName]) { emit UpdatedCurrentSubscriptionId(dapiName, subscriptionId); dapiNameToCurrentSubscriptionId[dapiName] = subscriptionId; } IAirseekerRegistry(airseekerRegistry).setDapiNameUpdateParameters( dapiName, updateParameters ); IAirseekerRegistry(airseekerRegistry).setDapiNameToBeActivated( dapiName ); } else { subscriptions[previousSubscriptionId] .nextSubscriptionId = subscriptionId; bytes32 currentSubscriptionId = dapiNameToCurrentSubscriptionId[ dapiName ]; if ( subscriptions[currentSubscriptionId].endTimestamp <= block.timestamp ) { updateEndedCurrentSubscriptionId( dapiName, currentSubscriptionId ); } } validateDataFeedReadiness(dataFeedId); if ( IApi3ServerV1(api3ServerV1).dapiNameHashToDataFeedId( keccak256(abi.encodePacked(dapiName)) ) != dataFeedId ) { IApi3ServerV1(api3ServerV1).setDapiName(dapiName, dataFeedId); } } /// @notice Updates the current subscription that has ended with the one /// that will end next /// @param dapiName dAPI name /// @param currentSubscriptionId Current subscription ID function updateEndedCurrentSubscriptionId( bytes32 dapiName, bytes32 currentSubscriptionId ) private { do { currentSubscriptionId = subscriptions[currentSubscriptionId] .nextSubscriptionId; } while ( currentSubscriptionId != bytes32(0) && subscriptions[currentSubscriptionId].endTimestamp <= block.timestamp ); emit UpdatedCurrentSubscriptionId(dapiName, currentSubscriptionId); dapiNameToCurrentSubscriptionId[dapiName] = currentSubscriptionId; if (currentSubscriptionId == bytes32(0)) { IAirseekerRegistry(airseekerRegistry).setDapiNameToBeDeactivated( dapiName ); } else { IAirseekerRegistry(airseekerRegistry).setDapiNameUpdateParameters( dapiName, subscriptionIdToUpdateParameters(currentSubscriptionId) ); } } /// @notice Prospects the subscription position in the queue. It iterates /// through the entire subscription queue, which is implemented as a linked /// list, and returns the previous and next nodes of the subscription to be /// added. /// It reverts if no suitable position can be found, which would be because /// the addition of the subscription to the queue does not upgrade its /// specs unambiguously or the addition of it results in the maximum queue /// length to be exceeded. /// @param dapiName dAPI name /// @param updateParameters Update parameters /// @param duration Subscription duration /// @return subscriptionId Subscription ID /// @return endTimestamp End timestamp /// @return previousSubscriptionId Previous subscription ID /// @return nextSubscriptionId Next subscription ID function prospectSubscriptionPositionInQueue( bytes32 dapiName, bytes calldata updateParameters, uint256 duration ) private view returns ( bytes32 subscriptionId, uint32 endTimestamp, bytes32 previousSubscriptionId, bytes32 nextSubscriptionId ) { subscriptionId = keccak256( abi.encodePacked(dapiName, keccak256(updateParameters)) ); endTimestamp = SafeCast.toUint32(block.timestamp + duration); ( uint256 deviationThresholdInPercentage, int224 deviationReference, uint256 heartbeatInterval ) = abi.decode(updateParameters, (uint256, int224, uint256)); uint256 newQueueLength = 0; Subscription storage queuedSubscription; for ( bytes32 queuedSubscriptionId = dapiNameToCurrentSubscriptionId[ dapiName ]; queuedSubscriptionId != bytes32(0); queuedSubscriptionId = queuedSubscription.nextSubscriptionId ) { queuedSubscription = subscriptions[queuedSubscriptionId]; UpdateParametersComparisonResult updateParametersComparisonResult = compareUpdateParametersWithQueued( deviationThresholdInPercentage, deviationReference, heartbeatInterval, queuedSubscription.updateParametersHash ); uint32 queuedSubscriptionEndTimestamp = queuedSubscription .endTimestamp; require( updateParametersComparisonResult == UpdateParametersComparisonResult.BetterThanQueued || endTimestamp > queuedSubscriptionEndTimestamp, "Subscription does not upgrade" ); if ( updateParametersComparisonResult == UpdateParametersComparisonResult.WorseThanQueued && queuedSubscriptionEndTimestamp > block.timestamp ) { previousSubscriptionId = queuedSubscriptionId; newQueueLength++; } if ( updateParametersComparisonResult == UpdateParametersComparisonResult.BetterThanQueued && endTimestamp < queuedSubscriptionEndTimestamp ) { nextSubscriptionId = queuedSubscriptionId; for ( ; queuedSubscriptionId != bytes32(0); queuedSubscriptionId = subscriptions[queuedSubscriptionId] .nextSubscriptionId ) { newQueueLength++; } break; } } require( newQueueLength < maximumSubscriptionQueueLength, "Subscription queue full" ); } /// @notice Compares the update parameters with the ones that belong to a /// queued subscription /// @param deviationThresholdInPercentage Deviation threshold in percentage /// @param deviationReference Deviation reference /// @param heartbeatInterval Heartbeat interval /// @param queuedUpdateParametersHash Queued update parameters hash /// @return Update parameters comparison result function compareUpdateParametersWithQueued( uint256 deviationThresholdInPercentage, int224 deviationReference, uint256 heartbeatInterval, bytes32 queuedUpdateParametersHash ) private view returns (UpdateParametersComparisonResult) { // The update parameters that belong to a queued subscription are // guaranteed to have been stored in the hash map ( uint256 queuedDeviationThresholdInPercentage, int224 queuedDeviationReference, uint256 queuedHeartbeatInterval ) = abi.decode( updateParametersHashToValue[queuedUpdateParametersHash], (uint256, int224, uint256) ); require( deviationReference == queuedDeviationReference, "Deviation references not equal" ); if ( (deviationThresholdInPercentage == queuedDeviationThresholdInPercentage) && (heartbeatInterval == queuedHeartbeatInterval) ) { return UpdateParametersComparisonResult.EqualToQueued; } else if ( (deviationThresholdInPercentage <= queuedDeviationThresholdInPercentage) && (heartbeatInterval <= queuedHeartbeatInterval) ) { return UpdateParametersComparisonResult.BetterThanQueued; } else if ( (deviationThresholdInPercentage >= queuedDeviationThresholdInPercentage) && (heartbeatInterval >= queuedHeartbeatInterval) ) { return UpdateParametersComparisonResult.WorseThanQueued; } else { // This is hit when the set of parameters are superior to each // other in different aspects, in which case they should not be // allowed to be in the same queue revert("Update parameters incomparable"); } } /// @notice Validates the readiness of the data feed. The data feed must /// have been updated on Api3ServerV1 in the last `MAXIMUM_DAPI_UPDATE_AGE` /// and registered on AirseekerRegistry. /// @param dataFeedId Data feed ID function validateDataFeedReadiness(bytes32 dataFeedId) private view { (, uint32 timestamp) = IApi3ServerV1(api3ServerV1).dataFeeds( dataFeedId ); require( block.timestamp <= timestamp + MAXIMUM_DAPI_UPDATE_AGE, "Data feed value stale" ); require( IAirseekerRegistry(airseekerRegistry).dataFeedIsRegistered( dataFeedId ), "Data feed not registered" ); } /// @notice Verifies the dAPI management Merkle proof /// @param dapiName dAPI name /// @param dataFeedId Data feed ID /// @param sponsorWallet Sponsor wallet address /// @param dapiManagementMerkleData ABI-encoded dAPI management Merkle root /// and proof function verifyDapiManagementMerkleProof( bytes32 dapiName, bytes32 dataFeedId, address sponsorWallet, bytes calldata dapiManagementMerkleData ) private view { require(dapiName != bytes32(0), "dAPI name zero"); ( bytes32 dapiManagementMerkleRoot, bytes32[] memory dapiManagementMerkleProof ) = abi.decode(dapiManagementMerkleData, (bytes32, bytes32[])); require( hashes[DAPI_MANAGEMENT_MERKLE_ROOT_HASH_TYPE].value == dapiManagementMerkleRoot, "Invalid root" ); require( MerkleProof.verify( dapiManagementMerkleProof, dapiManagementMerkleRoot, keccak256( bytes.concat( keccak256( abi.encode(dapiName, dataFeedId, sponsorWallet) ) ) ) ), "Invalid proof" ); } function verifyDapiManagementAndDapiPricingMerkleProofs( bytes32 dapiName, bytes32 dataFeedId, address sponsorWallet, bytes calldata updateParameters, uint256 duration, uint256 price, bytes calldata dapiManagementAndDapiPricingMerkleData ) private view { require(dapiName != bytes32(0), "dAPI name zero"); require( updateParameters.length == UPDATE_PARAMETERS_LENGTH, "Update parameters length invalid" ); require(duration != 0, "Duration zero"); require(price != 0, "Price zero"); ( bytes32 dapiManagementMerkleRoot, bytes32[] memory dapiManagementMerkleProof, bytes32 dapiPricingMerkleRoot, bytes32[] memory dapiPricingMerkleProof ) = abi.decode( dapiManagementAndDapiPricingMerkleData, (bytes32, bytes32[], bytes32, bytes32[]) ); require( hashes[DAPI_MANAGEMENT_MERKLE_ROOT_HASH_TYPE].value == dapiManagementMerkleRoot, "Invalid root" ); require( MerkleProof.verify( dapiManagementMerkleProof, dapiManagementMerkleRoot, keccak256( bytes.concat( keccak256( abi.encode(dapiName, dataFeedId, sponsorWallet) ) ) ) ), "Invalid proof" ); require( hashes[DAPI_PRICING_MERKLE_ROOT_HASH_TYPE].value == dapiPricingMerkleRoot, "Invalid root" ); require( MerkleProof.verify( dapiPricingMerkleProof, dapiPricingMerkleRoot, keccak256( bytes.concat( keccak256( abi.encode( dapiName, block.chainid, updateParameters, duration, price ) ) ) ) ), "Invalid proof" ); } /// @notice Verifies the signed API URL Merkle proof /// @param airnode Airnode address /// @param signedApiUrl Signed API URL /// @param signedApiUrlMerkleData ABI-encoded signed API URL Merkle root /// and proof function verifySignedApiUrlMerkleProof( address airnode, string calldata signedApiUrl, bytes calldata signedApiUrlMerkleData ) private view { ( bytes32 signedApiUrlMerkleRoot, bytes32[] memory signedApiUrlMerkleProof ) = abi.decode(signedApiUrlMerkleData, (bytes32, bytes32[])); require( hashes[SIGNED_API_URL_MERKLE_ROOT_HASH_TYPE].value == signedApiUrlMerkleRoot, "Invalid root" ); require( MerkleProof.verify( signedApiUrlMerkleProof, signedApiUrlMerkleRoot, keccak256( bytes.concat(keccak256(abi.encode(airnode, signedApiUrl))) ) ), "Invalid proof" ); } /// @notice Derives the Beacon ID from the Airnode address and template ID /// @param airnode Airnode address /// @param templateId Template ID /// @return beaconId Beacon ID function deriveBeaconId( address airnode, bytes32 templateId ) private pure returns (bytes32 beaconId) { beaconId = keccak256(abi.encodePacked(airnode, templateId)); } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/SelfMulticall.sol";
import "./RoleDeriver.sol";
import "./interfaces/IAccessControlRegistryAdminned.sol";
import "./interfaces/IAccessControlRegistry.sol";
/// @title Contract to be inherited by contracts whose adminship functionality
/// will be implemented using AccessControlRegistry
contract AccessControlRegistryAdminned is
SelfMulticall,
RoleDeriver,
IAccessControlRegistryAdminned
{
/// @notice AccessControlRegistry contract address
address public immutable override accessControlRegistry;
/// @notice Admin role description
string public override adminRoleDescription;
bytes32 internal immutable adminRoleDescriptionHash;
/// @dev Contracts deployed with the same admin role descriptions will have
/// the same roles, meaning that granting an account a role will authorize
/// it in multiple contracts. Unless you want your deployed contract to
/// share the role configuration of another contract, use a unique admin
/// role description.
/// @param _accessControlRegistry AccessControlRegistry contract address
/// @param _adminRoleDescription Admin role description
constructor(
address _accessControlRegistry,
string memory _adminRoleDescription
) {
require(_accessControlRegistry != address(0), "ACR address zero");
require(
bytes(_adminRoleDescription).length > 0,
"Admin role description empty"
);
accessControlRegistry = _accessControlRegistry;
adminRoleDescription = _adminRoleDescription;
adminRoleDescriptionHash = keccak256(
abi.encodePacked(_adminRoleDescription)
);
}
/// @notice Derives the admin role for the specific manager address
/// @param manager Manager address
/// @return adminRole Admin role
function _deriveAdminRole(
address manager
) internal view returns (bytes32 adminRole) {
adminRole = _deriveRole(
_deriveRootRole(manager),
adminRoleDescriptionHash
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./AccessControlRegistryAdminned.sol";
import "./interfaces/IAccessControlRegistryAdminnedWithManager.sol";
/// @title Contract to be inherited by contracts with manager whose adminship
/// functionality will be implemented using AccessControlRegistry
/// @notice The manager address here is expected to belong to an
/// AccessControlRegistry user that is a multisig/DAO
contract AccessControlRegistryAdminnedWithManager is
AccessControlRegistryAdminned,
IAccessControlRegistryAdminnedWithManager
{
/// @notice Address of the manager that manages the related
/// AccessControlRegistry roles
/// @dev The mutability of the manager role can be implemented by
/// designating an OwnableCallForwarder contract as the manager. The
/// ownership of this contract can then be transferred, effectively
/// transferring managership.
address public immutable override manager;
/// @notice Admin role
/// @dev Since `manager` is immutable, so is `adminRole`
bytes32 public immutable override adminRole;
/// @param _accessControlRegistry AccessControlRegistry contract address
/// @param _adminRoleDescription Admin role description
/// @param _manager Manager address
constructor(
address _accessControlRegistry,
string memory _adminRoleDescription,
address _manager
)
AccessControlRegistryAdminned(
_accessControlRegistry,
_adminRoleDescription
)
{
require(_manager != address(0), "Manager address zero");
manager = _manager;
adminRole = _deriveAdminRole(_manager);
}
}// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../vendor/@openzeppelin/[email protected]/access/Ownable.sol"; import "./interfaces/IHashRegistry.sol"; import "../vendor/@openzeppelin/[email protected]/utils/cryptography/MessageHashUtils.sol"; import "../vendor/@openzeppelin/[email protected]/utils/cryptography/ECDSA.sol"; /// @title A contract where a value for each hash type can be registered using /// the signatures of the respective signers that are set by the contract owner /// @notice Hashes are identified by a unique "hash type", which is a `bytes32` /// type that can be determined based on any arbitrary convention. The contract /// owner can set a list of signers for each hash type. For a hash value to be /// registered, its signers must be set by the contract owner, and valid /// signatures by each signer must be provided. The hash values are bundled /// with timestamps that act as nonces, meaning that each registration must /// be with a larger timestamp than the previous. The contract owner can /// override previously registered hashes. /// A signer can sign a delegation message that allows the delegate to sign /// hashes on their behalf across all instances of this contract until the /// specified time. This delegation is irrevocable by design (as revoking /// across all instances would be error-prone). To undo an unwanted delegation, /// the signer must be swapped out by the contract owner until the delegation /// runs out. /// @dev This contract can be used in standalone form to be referred to through /// external calls, or inherited by the contract that will access the /// registered hashes internally. /// HashRegistry is intended for use-cases where signatures and delegations /// need to apply universally across domains, which is why it is blind to the /// domain (unlike ERC-712). However, the inheriting contract can implement the /// type hashes to be domain-specific. contract HashRegistry is Ownable, IHashRegistry { struct Hash { bytes32 value; uint256 timestamp; } /// @notice Hash type to the last registered value and timestamp mapping(bytes32 => Hash) public override hashes; /// @notice Hash type to the hash of the array of signer addresses mapping(bytes32 => bytes32) public override hashTypeToSignersHash; uint256 private constant ECDSA_SIGNATURE_LENGTH = 65; // Length of abi.encode(uint256, bytes, bytes), where the bytes types are // ECDSA signatures padded to the next largest multiple of 32 bytes, which // is 96 uint256 private constant DELEGATED_SIGNATURE_LENGTH = 32 + 32 + 32 + (32 + 96) + (32 + 96); bytes32 private constant HASHREGISTRY_SIGNATURE_DELEGATION_HASH_TYPE = keccak256(abi.encodePacked("HashRegistry signature delegation")); /// @param initialOwner Initial owner address constructor(address initialOwner) Ownable(initialOwner) {} /// @notice Returns the owner address /// @return Owner address function owner() public view virtual override(Ownable, IOwnable) returns (address) { return super.owner(); } /// @notice Called by the owner to renounce the ownership of the contract function renounceOwnership() public virtual override(Ownable, IOwnable) { return super.renounceOwnership(); } /// @notice Called by the owner to transfer the ownership of the contract /// @param newOwner New owner address function transferOwnership( address newOwner ) public virtual override(Ownable, IOwnable) { return super.transferOwnership(newOwner); } /// @notice Called by the contract owner to set signers for a hash type. /// The signer addresses must be in ascending order. /// @param hashType Hash type /// @param signers Signer addresses function setSigners( bytes32 hashType, address[] calldata signers ) external override onlyOwner { require(hashType != bytes32(0), "Hash type zero"); uint256 signersCount = signers.length; require(signersCount != 0, "Signers empty"); require(signers[0] != address(0), "First signer address zero"); for (uint256 ind = 1; ind < signersCount; ind++) { require( signers[ind] > signers[ind - 1], "Signers not in ascending order" ); } hashTypeToSignersHash[hashType] = keccak256(abi.encodePacked(signers)); emit SetSigners(hashType, signers); } /// @notice Called by the owner to set a hash. Overrides previous /// registrations and is allowed to set the value to `bytes32(0)`. /// @param hashType Hash type /// @param hashValue Hash value function setHash( bytes32 hashType, bytes32 hashValue ) external override onlyOwner { hashes[hashType] = Hash({value: hashValue, timestamp: block.timestamp}); emit SetHash(hashType, hashValue, block.timestamp); } /// @notice Registers the hash value and timestamp for the respective type. /// The hash value cannot be zero. /// The timestamp must not exceed the block timestamp, yet be larger than /// the timestamp of the previous registration. /// The signers must have been set for the hash type, and the signatures /// must be sorted for the respective signer addresses to be in ascending /// order. /// Each signature can either be a standalone signature by the respective /// signer, or a signature by the signer's delegate, encoded along with /// the delegation end timestamp and delegation signature. /// @param hashType Hash type /// @param hashValue Hash value /// @param hashTimestamp Hash timestamp /// @param signatures Signatures function registerHash( bytes32 hashType, bytes32 hashValue, uint256 hashTimestamp, bytes[] calldata signatures ) external override { require(hashValue != bytes32(0), "Hash value zero"); require(hashTimestamp <= block.timestamp, "Hash timestamp from future"); require( hashTimestamp > hashes[hashType].timestamp, "Hash timestamp not more recent" ); bytes32 signersHash = hashTypeToSignersHash[hashType]; require(signersHash != bytes32(0), "Signers not set"); uint256 signaturesCount = signatures.length; address[] memory signers = new address[](signaturesCount); bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash( keccak256(abi.encodePacked(hashType, hashValue, hashTimestamp)) ); for (uint256 ind = 0; ind < signaturesCount; ind++) { uint256 signatureLength = signatures[ind].length; if (signatureLength == ECDSA_SIGNATURE_LENGTH) { signers[ind] = ECDSA.recover( ethSignedMessageHash, signatures[ind] ); } else if (signatureLength == DELEGATED_SIGNATURE_LENGTH) { ( uint256 delegationEndTimestamp, bytes memory delegationSignature, bytes memory hashSignature ) = abi.decode(signatures[ind], (uint256, bytes, bytes)); require( block.timestamp < delegationEndTimestamp, "Delegation ended" ); signers[ind] = ECDSA.recover( MessageHashUtils.toEthSignedMessageHash( keccak256( abi.encodePacked( signatureDelegationHashType(), ECDSA.recover( ethSignedMessageHash, hashSignature ), delegationEndTimestamp ) ) ), delegationSignature ); } else { revert("Invalid signature length"); } } require( signersHash == keccak256(abi.encodePacked(signers)), "Signature mismatch" ); hashes[hashType] = Hash({value: hashValue, timestamp: hashTimestamp}); emit RegisteredHash(hashType, hashValue, hashTimestamp); } /// @notice Returns the signature delegation hash type used in delegation /// signatures /// @dev Delegation signatures signed with a signature delegation hash type /// will apply universally across all HashRegistry instances that use that /// same signature delegation hash type. The inheriting contract can /// specify a special signature delegation hash type by overriding this /// function. /// @return Signature delegation hash type function signatureDelegationHashType() public view virtual override returns (bytes32) { return HASHREGISTRY_SIGNATURE_DELEGATION_HASH_TYPE; } /// @notice Returns get the hash value for the type /// @param hashType Hash type /// @return hashValue Hash value function getHashValue( bytes32 hashType ) external view override returns (bytes32 hashValue) { hashValue = hashes[hashType].value; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../vendor/@openzeppelin/[email protected]/access/IAccessControl.sol"; import "../../utils/interfaces/ISelfMulticall.sol"; interface IAccessControlRegistry is IAccessControl, ISelfMulticall { event InitializedManager( bytes32 indexed rootRole, address indexed manager, address sender ); event InitializedRole( bytes32 indexed role, bytes32 indexed adminRole, string description, address sender ); function initializeManager(address manager) external; function initializeRoleAndGrantToSender( bytes32 adminRole, string calldata description ) external returns (bytes32 role); }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/interfaces/ISelfMulticall.sol";
interface IAccessControlRegistryAdminned is ISelfMulticall {
function accessControlRegistry() external view returns (address);
function adminRoleDescription() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAccessControlRegistryAdminned.sol";
interface IAccessControlRegistryAdminnedWithManager is
IAccessControlRegistryAdminned
{
function manager() external view returns (address);
function adminRole() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IOwnable.sol";
interface IHashRegistry is IOwnable {
event SetSigners(bytes32 indexed hashType, address[] signers);
event SetHash(
bytes32 indexed hashType,
bytes32 hashValue,
uint256 hashTimestamp
);
event RegisteredHash(
bytes32 indexed hashType,
bytes32 hashValue,
uint256 hashTimestamp
);
function setSigners(bytes32 hashType, address[] calldata signers) external;
function setHash(bytes32 hashType, bytes32 hashValue) external;
function registerHash(
bytes32 hashType,
bytes32 hashValue,
uint256 hashTimestamp,
bytes[] calldata signatures
) external;
function signatureDelegationHashType() external view returns (bytes32);
function getHashValue(
bytes32 hashType
) external view returns (bytes32 hashValue);
function hashes(
bytes32 hashType
) external view returns (bytes32 hashValue, uint256 hashTimestamp);
function hashTypeToSignersHash(
bytes32 hashType
) external view returns (bytes32 signersHash);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external view returns (address);
function renounceOwnership() external;
function transferOwnership(address newOwner) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnableCallForwarder {
function forwardCall(
address forwardTarget,
bytes calldata forwardedCalldata
) external payable returns (bytes memory returnedData);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contract to be inherited by contracts that will derive
/// AccessControlRegistry roles
/// @notice If a contract interfaces with AccessControlRegistry and needs to
/// derive roles, it should inherit this contract instead of re-implementing
/// the logic
contract RoleDeriver {
/// @notice Derives the root role of the manager
/// @param manager Manager address
/// @return rootRole Root role
function _deriveRootRole(
address manager
) internal pure returns (bytes32 rootRole) {
rootRole = keccak256(abi.encodePacked(manager));
}
/// @notice Derives the role using its admin role and description
/// @dev This implies that roles adminned by the same role cannot have the
/// same description
/// @param adminRole Admin role
/// @param description Human-readable description of the role
/// @return role Role
function _deriveRole(
bytes32 adminRole,
string memory description
) internal pure returns (bytes32 role) {
role = _deriveRole(adminRole, keccak256(abi.encodePacked(description)));
}
/// @notice Derives the role using its admin role and description hash
/// @dev This implies that roles adminned by the same role cannot have the
/// same description
/// @param adminRole Admin role
/// @param descriptionHash Hash of the human-readable description of the
/// role
/// @return role Role
function _deriveRole(
bytes32 adminRole,
bytes32 descriptionHash
) internal pure returns (bytes32 role) {
role = keccak256(abi.encodePacked(adminRole, descriptionHash));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Sort.sol";
import "./QuickSelect.sol";
/// @title Contract to be inherited by contracts that will calculate the median
/// of an array
/// @notice The operation will be in-place, i.e., the array provided as the
/// argument will be modified.
contract Median is Sort, Quickselect {
/// @notice Returns the median of the array
/// @dev Uses an unrolled sorting implementation for shorter arrays and
/// quickselect for longer arrays for gas cost efficiency
/// @param array Array whose median is to be calculated
/// @return Median of the array
function median(int256[] memory array) internal pure returns (int256) {
uint256 arrayLength = array.length;
if (arrayLength <= MAX_SORT_LENGTH) {
sort(array);
if (arrayLength % 2 == 1) {
return array[arrayLength / 2];
} else {
assert(arrayLength != 0);
unchecked {
return
average(
array[arrayLength / 2 - 1],
array[arrayLength / 2]
);
}
}
} else {
if (arrayLength % 2 == 1) {
return array[quickselectK(array, arrayLength / 2)];
} else {
uint256 mid1;
uint256 mid2;
unchecked {
(mid1, mid2) = quickselectKPlusOne(
array,
arrayLength / 2 - 1
);
}
return average(array[mid1], array[mid2]);
}
}
}
/// @notice Averages two signed integers without overflowing
/// @param x Integer x
/// @param y Integer y
/// @return Average of integers x and y
function average(int256 x, int256 y) private pure returns (int256) {
unchecked {
int256 averageRoundedDownToNegativeInfinity = (x >> 1) +
(y >> 1) +
(x & y & 1);
// If the average rounded down to negative infinity is negative
// (i.e., its 256th sign bit is set), and one of (x, y) is even and
// the other one is odd (i.e., the 1st bit of their xor is set),
// add 1 to round the average down to zero instead.
// We will typecast the signed integer to unsigned to logical-shift
// int256(uint256(signedInt)) >> 255 ~= signedInt >>> 255
return
averageRoundedDownToNegativeInfinity +
(int256(
(uint256(averageRoundedDownToNegativeInfinity) >> 255)
) & (x ^ y));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contract to be inherited by contracts that will calculate the index
/// of the k-th and optionally (k+1)-th largest elements in the array
/// @notice Uses quickselect, which operates in-place, i.e., the array provided
/// as the argument will be modified.
contract Quickselect {
/// @notice Returns the index of the k-th largest element in the array
/// @param array Array in which k-th largest element will be searched
/// @param k K
/// @return indK Index of the k-th largest element
function quickselectK(
int256[] memory array,
uint256 k
) internal pure returns (uint256 indK) {
uint256 arrayLength = array.length;
assert(arrayLength > 0);
unchecked {
(indK, ) = quickselect(array, 0, arrayLength - 1, k, false);
}
}
/// @notice Returns the index of the k-th and (k+1)-th largest elements in
/// the array
/// @param array Array in which k-th and (k+1)-th largest elements will be
/// searched
/// @param k K
/// @return indK Index of the k-th largest element
/// @return indKPlusOne Index of the (k+1)-th largest element
function quickselectKPlusOne(
int256[] memory array,
uint256 k
) internal pure returns (uint256 indK, uint256 indKPlusOne) {
uint256 arrayLength = array.length;
assert(arrayLength > 1);
unchecked {
(indK, indKPlusOne) = quickselect(
array,
0,
arrayLength - 1,
k,
true
);
}
}
/// @notice Returns the index of the k-th largest element in the specified
/// section of the (potentially unsorted) array
/// @param array Array in which K will be searched for
/// @param lo Starting index of the section of the array that K will be
/// searched in
/// @param hi Last index of the section of the array that K will be
/// searched in
/// @param k K
/// @param selectKPlusOne If the index of the (k+1)-th largest element is
/// to be returned
/// @return indK Index of the k-th largest element
/// @return indKPlusOne Index of the (k+1)-th largest element (only set if
/// `selectKPlusOne` is `true`)
function quickselect(
int256[] memory array,
uint256 lo,
uint256 hi,
uint256 k,
bool selectKPlusOne
) private pure returns (uint256 indK, uint256 indKPlusOne) {
if (lo == hi) {
return (k, 0);
}
uint256 indPivot = partition(array, lo, hi);
if (k < indPivot) {
unchecked {
(indK, ) = quickselect(array, lo, indPivot - 1, k, false);
}
} else if (k > indPivot) {
unchecked {
(indK, ) = quickselect(array, indPivot + 1, hi, k, false);
}
} else {
indK = indPivot;
}
// Since Quickselect ends in the array being partitioned around the
// k-th largest element, we can continue searching towards right for
// the (k+1)-th largest element, which is useful in calculating the
// median of an array with even length
if (selectKPlusOne) {
unchecked {
indKPlusOne = indK + 1;
}
uint256 i;
unchecked {
i = indKPlusOne + 1;
}
uint256 arrayLength = array.length;
for (; i < arrayLength; ) {
if (array[i] < array[indKPlusOne]) {
indKPlusOne = i;
}
unchecked {
i++;
}
}
}
}
/// @notice Partitions the array into two around a pivot
/// @param array Array that will be partitioned
/// @param lo Starting index of the section of the array that will be
/// partitioned
/// @param hi Last index of the section of the array that will be
/// partitioned
/// @return pivotInd Pivot index
function partition(
int256[] memory array,
uint256 lo,
uint256 hi
) private pure returns (uint256 pivotInd) {
if (lo == hi) {
return lo;
}
int256 pivot = array[lo];
uint256 i = lo;
unchecked {
pivotInd = hi + 1;
}
while (true) {
do {
unchecked {
i++;
}
} while (i < array.length && array[i] < pivot);
do {
unchecked {
pivotInd--;
}
} while (array[pivotInd] > pivot);
if (i >= pivotInd) {
(array[lo], array[pivotInd]) = (array[pivotInd], array[lo]);
return pivotInd;
}
(array[i], array[pivotInd]) = (array[pivotInd], array[i]);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contract to be inherited by contracts that will sort an array using
/// an unrolled implementation
/// @notice The operation will be in-place, i.e., the array provided as the
/// argument will be modified.
contract Sort {
uint256 internal constant MAX_SORT_LENGTH = 9;
/// @notice Sorts the array
/// @param array Array to be sorted
function sort(int256[] memory array) internal pure {
uint256 arrayLength = array.length;
require(arrayLength <= MAX_SORT_LENGTH, "Array too long to sort");
// Do a binary search
if (arrayLength < 6) {
// Possible lengths: 1, 2, 3, 4, 5
if (arrayLength < 4) {
// Possible lengths: 1, 2, 3
if (arrayLength == 3) {
// Length: 3
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 0, 1);
} else if (arrayLength == 2) {
// Length: 2
swapIfFirstIsLarger(array, 0, 1);
}
// Do nothing for Length: 1
} else {
// Possible lengths: 4, 5
if (arrayLength == 5) {
// Length: 5
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 0, 2);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 0, 3);
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 1, 2);
} else {
// Length: 4
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 0, 2);
swapIfFirstIsLarger(array, 1, 2);
}
}
} else {
// Possible lengths: 6, 7, 8, 9
if (arrayLength < 8) {
// Possible lengths: 6, 7
if (arrayLength == 7) {
// Length: 7
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 5, 6);
swapIfFirstIsLarger(array, 0, 2);
swapIfFirstIsLarger(array, 4, 6);
swapIfFirstIsLarger(array, 3, 5);
swapIfFirstIsLarger(array, 2, 6);
swapIfFirstIsLarger(array, 1, 5);
swapIfFirstIsLarger(array, 0, 4);
swapIfFirstIsLarger(array, 2, 5);
swapIfFirstIsLarger(array, 0, 3);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 4, 5);
} else {
// Length: 6
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 4, 5);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 3, 5);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 0, 2);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 2, 3);
}
} else {
// Possible lengths: 8, 9
if (arrayLength == 9) {
// Length: 9
swapIfFirstIsLarger(array, 1, 8);
swapIfFirstIsLarger(array, 2, 7);
swapIfFirstIsLarger(array, 3, 6);
swapIfFirstIsLarger(array, 4, 5);
swapIfFirstIsLarger(array, 1, 4);
swapIfFirstIsLarger(array, 5, 8);
swapIfFirstIsLarger(array, 0, 2);
swapIfFirstIsLarger(array, 6, 7);
swapIfFirstIsLarger(array, 2, 6);
swapIfFirstIsLarger(array, 7, 8);
swapIfFirstIsLarger(array, 0, 3);
swapIfFirstIsLarger(array, 4, 5);
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 3, 5);
swapIfFirstIsLarger(array, 6, 7);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 1, 3);
swapIfFirstIsLarger(array, 5, 7);
swapIfFirstIsLarger(array, 4, 6);
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 5, 6);
swapIfFirstIsLarger(array, 7, 8);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 4, 5);
} else {
// Length: 8
swapIfFirstIsLarger(array, 0, 7);
swapIfFirstIsLarger(array, 1, 6);
swapIfFirstIsLarger(array, 2, 5);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 0, 3);
swapIfFirstIsLarger(array, 4, 7);
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 5, 6);
swapIfFirstIsLarger(array, 0, 1);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 4, 5);
swapIfFirstIsLarger(array, 6, 7);
swapIfFirstIsLarger(array, 3, 5);
swapIfFirstIsLarger(array, 2, 4);
swapIfFirstIsLarger(array, 1, 2);
swapIfFirstIsLarger(array, 3, 4);
swapIfFirstIsLarger(array, 5, 6);
swapIfFirstIsLarger(array, 2, 3);
swapIfFirstIsLarger(array, 4, 5);
swapIfFirstIsLarger(array, 3, 4);
}
}
}
}
/// @notice Swaps two elements of an array if the first element is greater
/// than the second
/// @param array Array whose elements are to be swapped
/// @param ind1 Index of the first element
/// @param ind2 Index of the second element
function swapIfFirstIsLarger(
int256[] memory array,
uint256 ind1,
uint256 ind2
) private pure {
if (array[ind1] > array[ind2]) {
(array[ind1], array[ind2]) = (array[ind2], array[ind1]);
}
}
}// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../vendor/@openzeppelin/[email protected]/access/Ownable.sol"; import "../utils/ExtendedSelfMulticall.sol"; import "./interfaces/IAirseekerRegistry.sol"; import "../vendor/@openzeppelin/[email protected]/utils/structs/EnumerableSet.sol"; import "./interfaces/IApi3ServerV1.sol"; /// @title A contract where active data feeds and their specs are registered by /// the contract owner for the respective Airseeker to refer to /// @notice Airseeker is an application that pushes API provider-signed data to /// chain when certain conditions are met so that the data feeds served on the /// Api3ServerV1 contract are updated according to the respective specs. In /// other words, this contract is an on-chain configuration file for an /// Airseeker (or multiple Airseekers in a setup with redundancy). /// The Airseeker must know which data feeds are active (and thus need to be /// updated), the constituting Airnode (the oracle node that API providers /// operate to sign data) addresses and request template IDs, what the /// respective on-chain data feed values are, what the update parameters are, /// and the URL of the signed APIs (from which Airseeker can fetch signed data) /// that are hosted by the respective API providers. /// The contract owner is responsible with leaving the state of this contract /// in a way that Airseeker expects. For example, if a dAPI name is activated /// without registering the respective data feed, the Airseeker will not have /// access to the data that it needs to execute updates. contract AirseekerRegistry is Ownable, ExtendedSelfMulticall, IAirseekerRegistry { using EnumerableSet for EnumerableSet.Bytes32Set; /// @notice Maximum number of Beacons in a Beacon set that can be /// registered /// @dev Api3ServerV1 introduces the concept of a Beacon, which is a /// single-source data feed. Api3ServerV1 allows Beacons to be read /// individually, or arbitrary combinations of them to be aggregated /// on-chain to form multiple-source data feeds, which are called Beacon /// sets. This contract does not support Beacon sets that consist of more /// than `MAXIMUM_BEACON_COUNT_IN_SET` Beacons to be registered. uint256 public constant override MAXIMUM_BEACON_COUNT_IN_SET = 21; /// @notice Maximum encoded update parameters length uint256 public constant override MAXIMUM_UPDATE_PARAMETERS_LENGTH = 1024; /// @notice Maximum signed API URL length uint256 public constant override MAXIMUM_SIGNED_API_URL_LENGTH = 256; /// @notice Api3ServerV1 contract address address public immutable override api3ServerV1; /// @notice Airnode address to signed API URL /// @dev An Airseeker can be configured to refer to additional signed APIs /// than the ones whose URLs are stored in this contract for redundancy mapping(address => string) public override airnodeToSignedApiUrl; /// @notice Data feed ID to encoded details mapping(bytes32 => bytes) public override dataFeedIdToDetails; // Api3ServerV1 uses Beacon IDs (see the `deriveBeaconId()` implementation) // and Beacon set IDs (see the `deriveBeaconSetId()` implementation) to // address data feeds. We use data feed ID as a general term to refer to a // Beacon ID/Beacon set ID. // A data feed ID is immutable (i.e., it always points to the same Beacon // or Beacon set). Api3ServerV1 allows a dAPI name to be pointed to a data // feed ID by privileged accounts to implement a mutable data feed // addressing scheme. // If the data feed ID or dAPI name should be used to read a data feed // depends on the use case. To support both schemes, AirseekerRegistry // allows data feeds specs to be defined with either the data feed ID or // the dAPI name. EnumerableSet.Bytes32Set private activeDataFeedIds; EnumerableSet.Bytes32Set private activeDapiNames; // Considering that the update parameters are typically reused between data // feeds, a hash map is used to avoid storing the same update parameters // redundantly mapping(bytes32 => bytes32) private dataFeedIdToUpdateParametersHash; mapping(bytes32 => bytes32) private dapiNameToUpdateParametersHash; mapping(bytes32 => bytes) private updateParametersHashToValue; // Length of `abi.encode(address, bytes32)` uint256 private constant DATA_FEED_DETAILS_LENGTH_FOR_SINGLE_BEACON = 32 + 32; // Length of `abi.encode(address[2], bytes32[2])` uint256 private constant DATA_FEED_DETAILS_LENGTH_FOR_BEACON_SET_WITH_TWO_BEACONS = 32 + 32 + (32 + 2 * 32) + (32 + 2 * 32); // Length of // `abi.encode(address[MAXIMUM_BEACON_COUNT_IN_SET], bytes32[MAXIMUM_BEACON_COUNT_IN_SET])` uint256 private constant MAXIMUM_DATA_FEED_DETAILS_LENGTH = 32 + 32 + (32 + MAXIMUM_BEACON_COUNT_IN_SET * 32) + (32 + MAXIMUM_BEACON_COUNT_IN_SET * 32); /// @dev Reverts if the data feed ID is zero /// @param dataFeedId Data feed ID modifier onlyNonZeroDataFeedId(bytes32 dataFeedId) { require(dataFeedId != bytes32(0), "Data feed ID zero"); _; } /// @dev Reverts if the dAPI name is zero /// @param dapiName dAPI name modifier onlyNonZeroDapiName(bytes32 dapiName) { require(dapiName != bytes32(0), "dAPI name zero"); _; } /// @dev Reverts if the update parameters are too long /// @param updateParameters Update parameters modifier onlyValidUpdateParameters(bytes calldata updateParameters) { require( updateParameters.length <= MAXIMUM_UPDATE_PARAMETERS_LENGTH, "Update parameters too long" ); _; } /// @param owner_ Owner address /// @param api3ServerV1_ Api3ServerV1 contract address constructor(address owner_, address api3ServerV1_) Ownable(owner_) { require(api3ServerV1_ != address(0), "Api3ServerV1 address zero"); api3ServerV1 = api3ServerV1_; } /// @notice Returns the owner address /// @return Owner address function owner() public view override(Ownable, IOwnable) returns (address) { return super.owner(); } /// @notice Overriden to be disabled function renounceOwnership() public pure override(Ownable, IOwnable) { revert("Ownership cannot be renounced"); } /// @notice Overriden to be disabled function transferOwnership( address ) public pure override(Ownable, IOwnable) { revert("Ownership cannot be transferred"); } /// @notice Called by the owner to set the data feed ID to be activated /// @param dataFeedId Data feed ID function setDataFeedIdToBeActivated( bytes32 dataFeedId ) external override onlyOwner onlyNonZeroDataFeedId(dataFeedId) { if (activeDataFeedIds.add(dataFeedId)) { emit ActivatedDataFeedId(dataFeedId); } } /// @notice Called by the owner to set the dAPI name to be activated /// @param dapiName dAPI name function setDapiNameToBeActivated( bytes32 dapiName ) external override onlyOwner onlyNonZeroDapiName(dapiName) { if (activeDapiNames.add(dapiName)) { emit ActivatedDapiName(dapiName); } } /// @notice Called by the owner to set the data feed ID to be deactivated /// @param dataFeedId Data feed ID function setDataFeedIdToBeDeactivated( bytes32 dataFeedId ) external override onlyOwner onlyNonZeroDataFeedId(dataFeedId) { if (activeDataFeedIds.remove(dataFeedId)) { emit DeactivatedDataFeedId(dataFeedId); } } /// @notice Called by the owner to set the dAPI name to be deactivated /// @param dapiName dAPI name function setDapiNameToBeDeactivated( bytes32 dapiName ) external override onlyOwner onlyNonZeroDapiName(dapiName) { if (activeDapiNames.remove(dapiName)) { emit DeactivatedDapiName(dapiName); } } /// @notice Called by the owner to set the data feed ID update parameters. /// The update parameters must be encoded in a format that Airseeker /// expects. /// @param dataFeedId Data feed ID /// @param updateParameters Update parameters function setDataFeedIdUpdateParameters( bytes32 dataFeedId, bytes calldata updateParameters ) external override onlyOwner onlyNonZeroDataFeedId(dataFeedId) onlyValidUpdateParameters(updateParameters) { bytes32 updateParametersHash = keccak256(updateParameters); if ( dataFeedIdToUpdateParametersHash[dataFeedId] != updateParametersHash ) { dataFeedIdToUpdateParametersHash[dataFeedId] = updateParametersHash; if ( updateParametersHashToValue[updateParametersHash].length != updateParameters.length ) { updateParametersHashToValue[ updateParametersHash ] = updateParameters; } emit UpdatedDataFeedIdUpdateParameters( dataFeedId, updateParameters ); } } /// @notice Called by the owner to set the dAPI name update parameters. /// The update parameters must be encoded in a format that Airseeker /// expects. /// @param dapiName dAPI name /// @param updateParameters Update parameters function setDapiNameUpdateParameters( bytes32 dapiName, bytes calldata updateParameters ) external override onlyOwner onlyNonZeroDapiName(dapiName) onlyValidUpdateParameters(updateParameters) { bytes32 updateParametersHash = keccak256(updateParameters); if (dapiNameToUpdateParametersHash[dapiName] != updateParametersHash) { dapiNameToUpdateParametersHash[dapiName] = updateParametersHash; if ( updateParametersHashToValue[updateParametersHash].length != updateParameters.length ) { updateParametersHashToValue[ updateParametersHash ] = updateParameters; } emit UpdatedDapiNameUpdateParameters(dapiName, updateParameters); } } /// @notice Called by the owner to set the signed API URL for the Airnode. /// The signed API must implement the specific interface that Airseeker /// expects. /// @param airnode Airnode address /// @param signedApiUrl Signed API URL function setSignedApiUrl( address airnode, string calldata signedApiUrl ) external override onlyOwner { require(airnode != address(0), "Airnode address zero"); require( abi.encodePacked(signedApiUrl).length <= MAXIMUM_SIGNED_API_URL_LENGTH, "Signed API URL too long" ); if ( keccak256(abi.encodePacked(airnodeToSignedApiUrl[airnode])) != keccak256(abi.encodePacked(signedApiUrl)) ) { airnodeToSignedApiUrl[airnode] = signedApiUrl; emit UpdatedSignedApiUrl(airnode, signedApiUrl); } } /// @notice Registers the data feed. In the case that the data feed is a /// Beacon, the details should be the ABI-encoded Airnode address and /// template ID. In the case that the data feed is a Beacon set, the /// details should be the ABI-encoded Airnode addresses array and template /// IDs array. /// @param dataFeedDetails Data feed details /// @return dataFeedId Data feed ID function registerDataFeed( bytes calldata dataFeedDetails ) external override returns (bytes32 dataFeedId) { uint256 dataFeedDetailsLength = dataFeedDetails.length; if ( dataFeedDetailsLength == DATA_FEED_DETAILS_LENGTH_FOR_SINGLE_BEACON ) { // dataFeedId maps to a Beacon (address airnode, bytes32 templateId) = abi.decode( dataFeedDetails, (address, bytes32) ); require(airnode != address(0), "Airnode address zero"); dataFeedId = deriveBeaconId(airnode, templateId); } else if ( dataFeedDetailsLength >= DATA_FEED_DETAILS_LENGTH_FOR_BEACON_SET_WITH_TWO_BEACONS ) { require( dataFeedDetailsLength <= MAXIMUM_DATA_FEED_DETAILS_LENGTH, "Data feed details too long" ); (address[] memory airnodes, bytes32[] memory templateIds) = abi .decode(dataFeedDetails, (address[], bytes32[])); require( abi.encode(airnodes, templateIds).length == dataFeedDetailsLength, "Data feed details trail" ); uint256 beaconCount = airnodes.length; require( beaconCount == templateIds.length, "Parameter length mismatch" ); bytes32[] memory beaconIds = new bytes32[](beaconCount); for (uint256 ind = 0; ind < beaconCount; ind++) { require(airnodes[ind] != address(0), "Airnode address zero"); beaconIds[ind] = deriveBeaconId( airnodes[ind], templateIds[ind] ); } dataFeedId = deriveBeaconSetId(beaconIds); } else { revert("Data feed details too short"); } if (dataFeedIdToDetails[dataFeedId].length != dataFeedDetailsLength) { dataFeedIdToDetails[dataFeedId] = dataFeedDetails; emit RegisteredDataFeed(dataFeedId, dataFeedDetails); } } /// @notice In an imaginary array consisting of the active data feed IDs /// and active dAPI names, picks the index-th identifier, and returns all /// data about the respective data feed that is available. Whenever data is /// not available (including the case where index does not correspond to an /// active data feed), returns empty values. /// @dev Airseeker uses this function to get all the data it needs about an /// active data feed with a single RPC call. /// Since active data feed IDs and dAPI names are kept in respective /// EnumerableSet types, addition and removal of items to these may change /// the order of the remaining items. Therefore, do not depend on an index /// to address a specific data feed consistently. /// @param index Index /// @return dataFeedId Data feed ID /// @return dapiName dAPI name (`bytes32(0)` if the active data feed is /// identified by a data feed ID) /// @return dataFeedDetails Data feed details /// @return dataFeedValue Data feed value read from Api3ServerV1 /// @return dataFeedTimestamp Data feed timestamp read from Api3ServerV1 /// @return beaconValues Beacon values read from Api3ServerV1 /// @return beaconTimestamps Beacon timestamps read from Api3ServerV1 /// @return updateParameters Update parameters /// @return signedApiUrls Signed API URLs of the Beacon Airnodes function activeDataFeed( uint256 index ) external view override returns ( bytes32 dataFeedId, bytes32 dapiName, bytes memory dataFeedDetails, int224 dataFeedValue, uint32 dataFeedTimestamp, int224[] memory beaconValues, uint32[] memory beaconTimestamps, bytes memory updateParameters, string[] memory signedApiUrls ) { uint256 activeDataFeedIdsLength = activeDataFeedIdCount(); if (index < activeDataFeedIdsLength) { dataFeedId = activeDataFeedIds.at(index); updateParameters = dataFeedIdToUpdateParameters(dataFeedId); } else if (index < activeDataFeedIdsLength + activeDapiNames.length()) { dapiName = activeDapiNames.at(index - activeDataFeedIdsLength); dataFeedId = IApi3ServerV1(api3ServerV1).dapiNameHashToDataFeedId( keccak256(abi.encodePacked(dapiName)) ); updateParameters = dapiNameToUpdateParameters(dapiName); } if (dataFeedId != bytes32(0)) { dataFeedDetails = dataFeedIdToDetails[dataFeedId]; (dataFeedValue, dataFeedTimestamp) = IApi3ServerV1(api3ServerV1) .dataFeeds(dataFeedId); } if (dataFeedDetails.length != 0) { if ( dataFeedDetails.length == DATA_FEED_DETAILS_LENGTH_FOR_SINGLE_BEACON ) { beaconValues = new int224[](1); beaconTimestamps = new uint32[](1); signedApiUrls = new string[](1); (address airnode, bytes32 templateId) = abi.decode( dataFeedDetails, (address, bytes32) ); (beaconValues[0], beaconTimestamps[0]) = IApi3ServerV1( api3ServerV1 ).dataFeeds(deriveBeaconId(airnode, templateId)); signedApiUrls[0] = airnodeToSignedApiUrl[airnode]; } else { (address[] memory airnodes, bytes32[] memory templateIds) = abi .decode(dataFeedDetails, (address[], bytes32[])); uint256 beaconCount = airnodes.length; beaconValues = new int224[](beaconCount); beaconTimestamps = new uint32[](beaconCount); signedApiUrls = new string[](beaconCount); for (uint256 ind = 0; ind < beaconCount; ind++) { (beaconValues[ind], beaconTimestamps[ind]) = IApi3ServerV1( api3ServerV1 ).dataFeeds( deriveBeaconId(airnodes[ind], templateIds[ind]) ); signedApiUrls[ind] = airnodeToSignedApiUrl[airnodes[ind]]; } } } } /// @notice Returns the number of active data feeds identified by a data /// feed ID or dAPI name /// @return Active data feed count function activeDataFeedCount() external view override returns (uint256) { return activeDataFeedIdCount() + activeDapiNameCount(); } /// @notice Returns the number of active data feeds identified by a data /// feed ID /// @return Active data feed ID count function activeDataFeedIdCount() public view override returns (uint256) { return activeDataFeedIds.length(); } /// @notice Returns the number of active data feeds identified by a dAPI /// name /// @return Active dAPI name count function activeDapiNameCount() public view override returns (uint256) { return activeDapiNames.length(); } /// @notice Data feed ID to update parameters /// @param dataFeedId Data feed ID /// @return updateParameters Update parameters function dataFeedIdToUpdateParameters( bytes32 dataFeedId ) public view override returns (bytes memory updateParameters) { updateParameters = updateParametersHashToValue[ dataFeedIdToUpdateParametersHash[dataFeedId] ]; } /// @notice dAPI name to update parameters /// @param dapiName dAPI name /// @return updateParameters Update parameters function dapiNameToUpdateParameters( bytes32 dapiName ) public view override returns (bytes memory updateParameters) { updateParameters = updateParametersHashToValue[ dapiNameToUpdateParametersHash[dapiName] ]; } /// @notice Returns if the data feed with ID is registered /// @param dataFeedId Data feed ID /// @return If the data feed with ID is registered function dataFeedIsRegistered( bytes32 dataFeedId ) external view override returns (bool) { return dataFeedIdToDetails[dataFeedId].length != 0; } /// @notice Derives the Beacon ID from the Airnode address and template ID /// @param airnode Airnode address /// @param templateId Template ID /// @return beaconId Beacon ID function deriveBeaconId( address airnode, bytes32 templateId ) private pure returns (bytes32 beaconId) { beaconId = keccak256(abi.encodePacked(airnode, templateId)); } /// @notice Derives the Beacon set ID from the Beacon IDs /// @param beaconIds Beacon IDs /// @return beaconSetId Beacon set ID function deriveBeaconSetId( bytes32[] memory beaconIds ) private pure returns (bytes32 beaconSetId) { beaconSetId = keccak256(abi.encode(beaconIds)); } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../access/interfaces/IOwnable.sol";
import "../../utils/interfaces/IExtendedSelfMulticall.sol";
interface IAirseekerRegistry is IOwnable, IExtendedSelfMulticall {
event ActivatedDataFeedId(bytes32 indexed dataFeedId);
event ActivatedDapiName(bytes32 indexed dapiName);
event DeactivatedDataFeedId(bytes32 indexed dataFeedId);
event DeactivatedDapiName(bytes32 indexed dapiName);
event UpdatedDataFeedIdUpdateParameters(
bytes32 indexed dataFeedId,
bytes updateParameters
);
event UpdatedDapiNameUpdateParameters(
bytes32 indexed dapiName,
bytes updateParameters
);
event UpdatedSignedApiUrl(address indexed airnode, string signedApiUrl);
event RegisteredDataFeed(bytes32 indexed dataFeedId, bytes dataFeedDetails);
function setDataFeedIdToBeActivated(bytes32 dataFeedId) external;
function setDapiNameToBeActivated(bytes32 dapiName) external;
function setDataFeedIdToBeDeactivated(bytes32 dataFeedId) external;
function setDapiNameToBeDeactivated(bytes32 dapiName) external;
function setDataFeedIdUpdateParameters(
bytes32 dataFeedId,
bytes calldata updateParameters
) external;
function setDapiNameUpdateParameters(
bytes32 dapiName,
bytes calldata updateParameters
) external;
function setSignedApiUrl(
address airnode,
string calldata signedApiUrl
) external;
function registerDataFeed(
bytes calldata dataFeedDetails
) external returns (bytes32 dataFeedId);
function activeDataFeed(
uint256 index
)
external
view
returns (
bytes32 dataFeedId,
bytes32 dapiName,
bytes memory dataFeedDetails,
int224 dataFeedValue,
uint32 dataFeedTimestamp,
int224[] memory beaconValues,
uint32[] memory beaconTimestamps,
bytes memory updateParameters,
string[] memory signedApiUrls
);
function activeDataFeedCount() external view returns (uint256);
function activeDataFeedIdCount() external view returns (uint256);
function activeDapiNameCount() external view returns (uint256);
function dataFeedIdToUpdateParameters(
bytes32 dataFeedId
) external view returns (bytes memory updateParameters);
function dapiNameToUpdateParameters(
bytes32 dapiName
) external view returns (bytes memory updateParameters);
function dataFeedIsRegistered(
bytes32 dataFeedId
) external view returns (bool);
function MAXIMUM_BEACON_COUNT_IN_SET() external view returns (uint256);
function MAXIMUM_UPDATE_PARAMETERS_LENGTH() external view returns (uint256);
function MAXIMUM_SIGNED_API_URL_LENGTH() external view returns (uint256);
function api3ServerV1() external view returns (address);
function airnodeToSignedApiUrl(
address airnode
) external view returns (string memory signedApiUrl);
function dataFeedIdToDetails(
bytes32 dataFeedId
) external view returns (bytes memory dataFeedDetails);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../access/interfaces/IHashRegistry.sol";
import "../../utils/interfaces/IExtendedSelfMulticall.sol";
interface IApi3MarketV2 is IHashRegistry, IExtendedSelfMulticall {
event SetAirseekerRegistry(address airseekerRegistry);
event BoughtSubscription(
bytes32 indexed dapiName,
bytes32 indexed subscriptionId,
bytes32 dataFeedId,
address sponsorWallet,
bytes updateParameters,
uint256 duration,
uint256 price,
uint256 paymentAmount
);
event CanceledSubscriptions(bytes32 indexed dapiName);
event UpdatedCurrentSubscriptionId(
bytes32 indexed dapiName,
bytes32 indexed subscriptionId
);
function setAirseekerRegistry(address airseekerRegistry_) external;
function buySubscription(
bytes32 dapiName,
bytes32 dataFeedId,
address payable sponsorWallet,
bytes calldata updateParameters,
uint256 duration,
uint256 price,
bytes calldata dapiManagementAndDapiPricingMerkleData
) external payable returns (bytes32 subscriptionId);
function cancelSubscriptions(bytes32 dapiName) external;
function updateCurrentSubscriptionId(bytes32 dapiName) external;
function updateDapiName(
bytes32 dapiName,
bytes32 dataFeedId,
address sponsorWallet,
bytes calldata dapiManagementMerkleData
) external;
function updateSignedApiUrl(
address airnode,
string calldata signedApiUrl,
bytes calldata signedApiUrlMerkleData
) external;
function multicallAndBuySubscription(
bytes[] calldata multicallData,
bytes32 dapiName,
bytes32 dataFeedId,
address payable sponsorWallet,
bytes calldata updateParameters,
uint256 duration,
uint256 price,
bytes calldata dapiManagementAndDapiPricingMerkleData
)
external
payable
returns (bytes[] memory returndata, bytes32 subscriptionId);
function tryMulticallAndBuySubscription(
bytes[] calldata tryMulticallData,
bytes32 dapiName,
bytes32 dataFeedId,
address payable sponsorWallet,
bytes calldata updateParameters,
uint256 duration,
uint256 price,
bytes calldata dapiManagementAndDapiPricingMerkleData
)
external
payable
returns (
bool[] memory successes,
bytes[] memory returndata,
bytes32 subscriptionId
);
function updateBeaconWithSignedData(
address airnode,
bytes32 templateId,
uint256 timestamp,
bytes calldata data,
bytes calldata signature
) external returns (bytes32 beaconId);
function updateBeaconSetWithBeacons(
bytes32[] calldata beaconIds
) external returns (bytes32 beaconSetId);
function deployApi3ReaderProxyV1(
bytes32 dapiName,
uint256 dappId,
bytes calldata metadata
) external returns (address api3ReaderProxyV1);
function registerDataFeed(
bytes calldata dataFeedDetails
) external returns (bytes32 dataFeedId);
function computeExpectedSponsorWalletBalance(
bytes32 dapiName
) external view returns (uint256 expectedSponsorWalletBalance);
function computeExpectedSponsorWalletBalanceAfterSubscriptionIsAdded(
bytes32 dapiName,
bytes calldata updateParameters,
uint256 duration,
uint256 price
) external view returns (uint256 expectedSponsorWalletBalance);
function getDapiData(
bytes32 dapiName
)
external
view
returns (
bytes memory dataFeedDetails,
int224 dapiValue,
uint32 dapiTimestamp,
int224[] memory beaconValues,
uint32[] memory beaconTimestamps,
bytes[] memory updateParameters,
uint32[] memory endTimestamps,
uint224[] memory dailyPrices
);
function getDataFeedData(
bytes32 dataFeedId
)
external
view
returns (
bytes memory dataFeedDetails,
int224 dataFeedValue,
uint32 dataFeedTimestamp,
int224[] memory beaconValues,
uint32[] memory beaconTimestamps
);
function subscriptionIdToUpdateParameters(
bytes32 subscriptionId
) external view returns (bytes memory updateParameters);
function DAPI_MANAGEMENT_MERKLE_ROOT_HASH_TYPE()
external
view
returns (bytes32);
function DAPI_PRICING_MERKLE_ROOT_HASH_TYPE()
external
view
returns (bytes32);
function SIGNED_API_URL_MERKLE_ROOT_HASH_TYPE()
external
view
returns (bytes32);
function MAXIMUM_DAPI_UPDATE_AGE() external view returns (uint256);
function api3ServerV1() external view returns (address);
function api3ReaderProxyV1Factory() external view returns (address);
function airseekerRegistry() external view returns (address);
function maximumSubscriptionQueueLength() external view returns (uint256);
function subscriptions(
bytes32 subscriptionId
)
external
view
returns (
bytes32 updateParametersHash,
uint32 endTimestamp,
uint224 dailyPrice,
bytes32 nextSubscriptionId
);
function dapiNameToCurrentSubscriptionId(
bytes32 dapiName
) external view returns (bytes32 currentSubscriptionId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IOevDapiServer.sol";
import "./IBeaconUpdatesWithSignedData.sol";
interface IApi3ServerV1 is IOevDapiServer, IBeaconUpdatesWithSignedData {
function readDataFeedWithId(
bytes32 dataFeedId
) external view returns (int224 value, uint32 timestamp);
function readDataFeedWithDapiNameHash(
bytes32 dapiNameHash
) external view returns (int224 value, uint32 timestamp);
function readDataFeedWithIdAsOevProxy(
bytes32 dataFeedId
) external view returns (int224 value, uint32 timestamp);
function readDataFeedWithDapiNameHashAsOevProxy(
bytes32 dapiNameHash
) external view returns (int224 value, uint32 timestamp);
function dataFeeds(
bytes32 dataFeedId
) external view returns (int224 value, uint32 timestamp);
function oevProxyToIdToDataFeed(
address proxy,
bytes32 dataFeedId
) external view returns (int224 value, uint32 timestamp);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../access/interfaces/IAccessControlRegistryAdminnedWithManager.sol";
import "../interfaces/IDataFeedServer.sol";
interface IApi3ServerV1OevExtension is
IAccessControlRegistryAdminnedWithManager,
IDataFeedServer
{
event Withdrew(address recipient, uint256 amount, address sender);
event PaidOevBid(
uint256 indexed dappId,
address indexed updater,
uint256 bidAmount,
uint256 signedDataTimestampCutoff,
address auctioneer
);
event UpdatedDappOevDataFeed(
uint256 indexed dappId,
address indexed updater,
bytes32 dataFeedId,
int224 updatedValue,
uint32 updatedTimestamp
);
function withdraw(address recipient, uint256 amount) external;
function payOevBid(
uint256 dappId,
uint256 bidAmount,
uint32 signedDataTimestampCutoff,
bytes calldata signature,
bytes calldata data
) external;
function updateDappOevDataFeed(
uint256 dappId,
bytes[] calldata signedData
)
external
returns (
bytes32 baseDataFeedId,
int224 updatedValue,
uint32 updatedTimestamp
);
function simulateDappOevDataFeedUpdate(
uint256 dappId,
bytes[] calldata signedData
)
external
returns (
bytes32 baseDataFeedId,
int224 updatedValue,
uint32 updatedTimestamp
);
function simulateExternalCall(
address target,
bytes calldata data
) external returns (bytes memory);
function oevDataFeed(
uint256 dappId,
bytes32 dataFeedId
) external view returns (int224 value, uint32 timestamp);
// solhint-disable-next-line func-name-mixedcase
function WITHDRAWER_ROLE_DESCRIPTION()
external
view
returns (string memory);
// solhint-disable-next-line func-name-mixedcase
function AUCTIONEER_ROLE_DESCRIPTION()
external
view
returns (string memory);
function withdrawerRole() external view returns (bytes32);
function auctioneerRole() external view returns (bytes32);
function api3ServerV1() external view returns (address);
function dappIdToLastPaidBid(
uint256 dappId
) external view returns (address updater, uint32 endTimestamp);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Interface that OEV bid payers (i.e., contracts that call
/// `payOevBid()` of Api3ServerV1OevExtension) must implement
interface IApi3ServerV1OevExtensionOevBidPayer {
/// @notice Called back by Api3ServerV1OevExtension after an OEV bid payer
/// has called `payOevBid()` of Api3ServerV1OevExtension. During the
/// callback, the OEV bid payer will be allowed to update the OEV feeds
/// of the respective dApp. Before returning, the OEV bid payer must ensure
/// that at least the bid amount has been sent to Api3ServerV1OevExtension.
/// The returndata must start with the keccak256 hash of
/// "Api3ServerV1OevExtensionOevBidPayer.onOevBidPayment".
/// @param bidAmount Bid amount
/// @param data Data that is passed through the callback
/// @return oevBidPaymentCallbackSuccess OEV bid payment callback success
/// code
function onOevBidPayment(
uint256 bidAmount,
bytes calldata data
) external returns (bytes32 oevBidPaymentCallbackSuccess);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IDataFeedServer.sol";
interface IBeaconUpdatesWithSignedData is IDataFeedServer {
function updateBeaconWithSignedData(
address airnode,
bytes32 templateId,
uint256 timestamp,
bytes calldata data,
bytes calldata signature
) external returns (bytes32 beaconId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../access/interfaces/IAccessControlRegistryAdminnedWithManager.sol";
import "./IDataFeedServer.sol";
interface IDapiServer is
IAccessControlRegistryAdminnedWithManager,
IDataFeedServer
{
event SetDapiName(
bytes32 indexed dataFeedId,
bytes32 indexed dapiName,
address sender
);
function setDapiName(bytes32 dapiName, bytes32 dataFeedId) external;
function dapiNameToDataFeedId(
bytes32 dapiName
) external view returns (bytes32);
// solhint-disable-next-line func-name-mixedcase
function DAPI_NAME_SETTER_ROLE_DESCRIPTION()
external
view
returns (string memory);
function dapiNameSetterRole() external view returns (bytes32);
function dapiNameHashToDataFeedId(
bytes32 dapiNameHash
) external view returns (bytes32 dataFeedId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/interfaces/IExtendedSelfMulticall.sol";
interface IDataFeedServer is IExtendedSelfMulticall {
event UpdatedBeaconWithSignedData(
bytes32 indexed beaconId,
int224 value,
uint32 timestamp
);
event UpdatedBeaconSetWithBeacons(
bytes32 indexed beaconSetId,
int224 value,
uint32 timestamp
);
function updateBeaconSetWithBeacons(
bytes32[] memory beaconIds
) external returns (bytes32 beaconSetId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../../access/interfaces/IAccessControlRegistryAdminnedWithManager.sol";
interface IOevAuctionHouse is IAccessControlRegistryAdminnedWithManager {
enum BidStatus {
None,
Placed,
Awarded,
FulfillmentReported,
FulfillmentConfirmed,
FulfillmentContradicted
}
event SetCollateralInBasisPoints(uint256 collateralInBasisPoints);
event SetProtocolFeeInBasisPoints(uint256 protocolFeeInBasisPoints);
event SetCollateralRateProxy(address collateralRateProxy);
event SetChainNativeCurrencyRateProxy(
uint256 indexed chainId,
address nativeCurrencyRateProxy
);
event WithdrewAccumulatedSlashedCollateral(
address recipient,
uint256 amount
);
event WithdrewAccumulatedProtocolFees(address recipient, uint256 amount);
event Deposited(
address indexed bidder,
uint256 amount,
uint256 bidderBalance,
address sender
);
event InitiatedWithdrawal(
address indexed bidder,
uint256 earliestWithdrawalTimestamp
);
event Withdrew(address indexed bidder, address recipient, uint256 amount);
event CanceledWithdrawal(address indexed bidder);
event PlacedBid(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
uint256 chainId,
uint256 bidAmount,
bytes bidDetails,
uint32 expirationTimestamp,
uint104 collateralAmount,
uint104 protocolFeeAmount
);
event ExpeditedBidExpiration(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
uint32 expirationTimestamp
);
event AwardedBid(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
bytes awardDetails,
uint256 bidderBalance
);
event ReportedFulfillment(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
bytes fulfillmentDetails
);
event ConfirmedFulfillment(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
uint256 bidderBalance,
uint256 accumulatedProtocolFees
);
event ContradictedFulfillment(
address indexed bidder,
bytes32 indexed bidTopic,
bytes32 indexed bidId,
uint256 bidderBalance,
uint256 accumulatedSlashedCollateral
);
error SenderIsNotTheManager();
error SenderIsNotAProxySetterOrTheManager();
error SenderIsNotAWithdrawerOrTheManager();
error SenderIsNotAnAuctioneer();
error ProxyAddressIsZero();
error ChainIdIsZero();
error RecipientAddressIsZero();
error WithdrawalAmountIsZero();
error InsufficientBalance();
error BidderAddressIsZero();
error DepositAmountIsZero();
error BidderHasAlreadyInitiatedWithdrawal();
error SenderHasNotInitiatedWithdrawal();
error BidderCannotWithdrawYet();
error BidAmountIsZero();
error BidDetailsAreEmpty();
error MaximumBidderDataLengthIsExceeded();
error BidLifetimeIsLongerThanMaximum();
error BidLifetimeIsShorterThanMinimum();
error BidIsAlreadyPlaced();
error MaxCollateralAmountIsExceeded();
error MaxProtocolFeeAmountIsExceeded();
error BidIsNotAwaitingAward();
error BidHasExpired();
error TimestampDoesNotExpediteExpiration();
error MaximumAuctioneerDataLengthIsExceeded();
error AwardDetailsAreEmpty();
error AwardHasExpired();
error BidderBalanceIsLowerThanTheLockedAmount();
error FulfillmentDetailsAreEmpty();
error BidIsNotAwaitingFulfillmentReport();
error BidFulfillmentCannotBeConfirmed();
error BidFulfillmentCannotBeContradicted();
error CollateralRateIsNotPositive();
error CollateralRateIsStale();
error NativeCurrencyRateIsNotPositive();
error NativeCurrencyRateIsStale();
function setProtocolFeeInBasisPoints(
uint256 protocolFeeInBasisPoints_
) external;
function setCollateralInBasisPoints(
uint256 collateralInBasisPoints_
) external;
function setCollateralRateProxy(address collateralRateProxy_) external;
function setChainNativeCurrencyRateProxy(
uint256 chainId,
address nativeCurrencyRateProxy
) external;
function withdrawAccumulatedSlashedCollateral(
address payable recipient,
uint256 amount
) external;
function withdrawAccumulatedProtocolFees(
address payable recipient,
uint256 amount
) external;
function depositForBidder(
address bidder
) external payable returns (uint256 bidderBalance);
function deposit() external payable returns (uint256 bidderBalance);
function initiateWithdrawal()
external
returns (uint256 earliestWithdrawalTimestamp);
function withdraw(address payable recipient, uint256 amount) external;
function cancelWithdrawal() external;
function placeBidWithExpiration(
bytes32 bidTopic,
uint256 chainId,
uint256 bidAmount,
bytes calldata bidDetails,
uint256 maxCollateralAmount,
uint256 maxProtocolFeeAmount,
uint32 expirationTimestamp
) external returns (uint104 collateralAmount, uint104 protocolFeeAmount);
function placeBid(
bytes32 bidTopic,
uint256 chainId,
uint256 bidAmount,
bytes calldata bidDetails,
uint256 maxCollateralAmount,
uint256 maxProtocolFeeAmount
)
external
returns (
uint32 expirationTimestamp,
uint104 collateralAmount,
uint104 protocolFeeAmount
);
function expediteBidExpiration(
bytes32 bidTopic,
bytes32 bidDetailsHash,
uint32 expirationTimestamp
) external;
function expediteBidExpirationMaximally(
bytes32 bidTopic,
bytes32 bidDetailsHash
) external returns (uint32 expirationTimestamp);
function awardBid(
address bidder,
bytes32 bidTopic,
bytes32 bidDetailsHash,
bytes calldata awardDetails,
uint256 awardExpirationTimestamp
) external returns (uint256 bidderBalance);
function reportFulfillment(
bytes32 bidTopic,
bytes32 bidDetailsHash,
bytes calldata fulfillmentDetails
) external;
function confirmFulfillment(
address bidder,
bytes32 bidTopic,
bytes32 bidDetailsHash
)
external
returns (uint256 bidderBalance, uint256 accumulatedProtocolFees_);
function contradictFulfillment(
address bidder,
bytes32 bidTopic,
bytes32 bidDetailsHash
)
external
returns (uint256 bidderBalance, uint256 accumulatedSlashedCollateral_);
function getCurrentCollateralAndProtocolFeeAmounts(
uint256 chainId,
uint256 bidAmount
)
external
view
returns (uint104 collateralAmount, uint104 protocolFeeAmount);
function PROXY_SETTER_ROLE_DESCRIPTION() external returns (string memory);
function WITHDRAWER_ROLE_DESCRIPTION() external returns (string memory);
function AUCTIONEER_ROLE_DESCRIPTION() external returns (string memory);
function WITHDRAWAL_WAITING_PERIOD() external returns (uint256);
function MAXIMUM_BID_LIFETIME() external returns (uint256);
function MINIMUM_BID_LIFETIME() external returns (uint256);
function FULFILLMENT_REPORTING_PERIOD() external returns (uint256);
function MAXIMUM_BIDDER_DATA_LENGTH() external returns (uint256);
function MAXIMUM_AUCTIONEER_DATA_LENGTH() external returns (uint256);
function proxySetterRole() external returns (bytes32);
function withdrawerRole() external returns (bytes32);
function auctioneerRole() external returns (bytes32);
function protocolFeeInBasisPoints() external returns (uint256);
function collateralInBasisPoints() external returns (uint256);
function collateralRateProxy() external returns (address);
function chainIdToNativeCurrencyRateProxy(
uint256 chainId
) external returns (address nativeCurrencyRateProxy);
function accumulatedSlashedCollateral() external returns (uint256);
function accumulatedProtocolFees() external returns (uint256);
function bidderToBalance(address bidder) external returns (uint256 balance);
function bidderToEarliestWithdrawalTimestamp(
address bidder
) external returns (uint256 earliestWithdrawalTimestamp);
function bids(
bytes32 bidId
)
external
returns (
BidStatus status,
uint32 expirationTimestamp,
uint104 collateralAmount,
uint104 protocolFeeAmount
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IOevDataFeedServer.sol";
import "./IDapiServer.sol";
interface IOevDapiServer is IOevDataFeedServer, IDapiServer {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IDataFeedServer.sol";
interface IOevDataFeedServer is IDataFeedServer {
event UpdatedOevProxyBeaconWithSignedData(
bytes32 indexed beaconId,
address indexed proxy,
bytes32 indexed updateId,
int224 value,
uint32 timestamp
);
event UpdatedOevProxyBeaconSetWithSignedData(
bytes32 indexed beaconSetId,
address indexed proxy,
bytes32 indexed updateId,
int224 value,
uint32 timestamp
);
event Withdrew(
address indexed oevProxy,
address oevBeneficiary,
uint256 amount
);
function updateOevProxyDataFeedWithSignedData(
address oevProxy,
bytes32 dataFeedId,
bytes32 updateId,
uint256 timestamp,
bytes calldata data,
bytes[] calldata packedOevUpdateSignatures
) external payable;
function withdraw(address oevProxy) external;
function oevProxyToBalance(
address oevProxy
) external view returns (uint256 balance);
}// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../../vendor/@openzeppelin/[email protected]/proxy/utils/UUPSUpgradeable.sol"; import "../../vendor/@openzeppelin/[email protected]/access/OwnableUpgradeable.sol"; import "../../vendor/@chainlink/[email protected]/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol"; import "./interfaces/IApi3ReaderProxyV1.sol"; import "../interfaces/IApi3ServerV1.sol"; import "../interfaces/IApi3ServerV1OevExtension.sol"; /// @title UUPS-upgradeable IApi3ReaderProxy and AggregatorV2V3Interface /// implementation that is designed to be deployed by Api3ReaderProxyV1Factory /// @notice The owner of this contract is allowed to upgrade it. In the case /// that it is deployed by Api3ReaderProxyV1Factory, the owner will be the /// owner of Api3ReaderProxyV1Factory at the time of deployment. /// @dev For a gas-cheap `read()` implementation, this upgradeable contract /// uses immutable variables (rather than initializable ones). To enable this, /// an Api3ReaderProxyV1 needs to be deployed for each unique combination of /// variables. The end user does not need to concern themselves with this, as /// Api3ReaderProxyV1Factory abstracts this detail away. /// Refer to https://github.com/api3dao/migrate-from-chainlink-to-api3 for more /// information about the Chainlink interface implementation. contract Api3ReaderProxyV1 is UUPSUpgradeable, OwnableUpgradeable, AggregatorV2V3Interface, IApi3ReaderProxyV1 { /// @notice Api3ServerV1 contract address address public immutable override api3ServerV1; /// @notice Api3ServerV1OevExtension contract address address public immutable override api3ServerV1OevExtension; /// @notice dAPI name as a bytes32 string bytes32 public immutable override dapiName; /// @notice dApp ID uint256 public immutable override dappId; // Api3ServerV1 interface expects the dAPI name hash. keccak256 is // typically expensive on ZK roll-ups, so we compute it once and store it // to use during reads. bytes32 private immutable dapiNameHash; /// @dev Parameters are validated by Api3ReaderProxyV1Factory /// @param api3ServerV1OevExtension_ Api3ServerV1OevExtension contract /// address /// @param dapiName_ dAPI name as a bytes32 string /// @param dappId_ dApp ID constructor( address api3ServerV1OevExtension_, bytes32 dapiName_, uint256 dappId_ ) { api3ServerV1OevExtension = api3ServerV1OevExtension_; api3ServerV1 = IApi3ServerV1OevExtension(api3ServerV1OevExtension_) .api3ServerV1(); dapiName = dapiName_; dappId = dappId_; dapiNameHash = keccak256(abi.encodePacked(dapiName)); _disableInitializers(); } /// @notice Initializes the contract with the initial owner /// @param initialOwner Initial owner function initialize(address initialOwner) external override initializer { __Ownable_init(initialOwner); } /// @notice Returns the current value and timestamp of the API3 data feed /// associated with the proxy contract /// @dev Reads the base feed that is associated to the dAPI and the OEV /// feed that is associated to the dApp–dAPI pair, and returns the value /// that is updated more recently /// @return value Data feed value /// @return timestamp Data feed timestamp function read() public view override returns (int224 value, uint32 timestamp) { bytes32 dataFeedId = IApi3ServerV1(api3ServerV1) .dapiNameHashToDataFeedId(dapiNameHash); if (dataFeedId == bytes32(0)) { revert DapiNameIsNotSet(); } (int224 baseDapiValue, uint32 baseDapiTimestamp) = IApi3ServerV1( api3ServerV1 ).dataFeeds(dataFeedId); ( int224 oevDapiValue, uint32 oevDapiTimestamp ) = IApi3ServerV1OevExtension(api3ServerV1OevExtension).oevDataFeed( dappId, dataFeedId ); if (oevDapiTimestamp > baseDapiTimestamp) { (value, timestamp) = (oevDapiValue, oevDapiTimestamp); } else { (value, timestamp) = (baseDapiValue, baseDapiTimestamp); } if (timestamp == 0) { revert DataFeedIsNotInitialized(); } } /// @dev AggregatorV2V3Interface users are already responsible with /// validating the values that they receive (e.g., revert if the spot price /// of an asset is negative). Therefore, this contract omits validation. function latestAnswer() external view override returns (int256 value) { (value, ) = read(); } /// @dev A Chainlink feed contract returns the block timestamp at which the /// feed was last updated. On the other hand, an API3 feed timestamp /// denotes the point in time at which the first-party oracles signed the /// data used to do the last update. We find this to be a reasonable /// approximation, considering that usually the timestamp is only used to /// check if the last update is stale. function latestTimestamp() external view override returns (uint256 timestamp) { (, timestamp) = read(); } /// @dev API3 feeds are updated asynchronously and not in rounds function latestRound() external pure override returns (uint256) { revert FunctionIsNotSupported(); } /// @dev Functions that use the round ID as an argument are not supported function getAnswer(uint256) external pure override returns (int256) { revert FunctionIsNotSupported(); } /// @dev Functions that use the round ID as an argument are not supported function getTimestamp(uint256) external pure override returns (uint256) { revert FunctionIsNotSupported(); } /// @dev API3 feeds always use 18 decimals function decimals() external pure override returns (uint8) { return 18; } /// @dev The dApp ID and dAPI name act as the description, and this is left /// empty to save gas on contract deployment function description() external pure override returns (string memory) { return ""; } /// @dev A unique version is chosen to easily check if an unverified /// contract that acts as a Chainlink feed is an Api3ReaderProxyV1 function version() external pure override returns (uint256) { return 4913; } /// @dev Functions that use the round ID as an argument are not supported function getRoundData( uint80 ) external pure override returns (uint80, int256, uint256, uint256, uint80) { revert FunctionIsNotSupported(); } /// @dev Rounds IDs are returned as `0` as invalid values. /// Similar to `latestAnswer()`, we leave the validation of the returned /// value to the caller. function latestRoundData() external view override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { roundId = answeredInRound = 0; (answer, startedAt) = read(); updatedAt = startedAt; } /// @param newImplementation New implementation contract address /// @dev Only the owner can upgrade this contract function _authorizeUpgrade( address newImplementation ) internal virtual override onlyOwner {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../../vendor/@openzeppelin/[email protected]/access/Ownable.sol"; import "./interfaces/IApi3ReaderProxyV1Factory.sol"; import "../../vendor/@openzeppelin/[email protected]/proxy/ERC1967/ERC1967Proxy.sol"; import "../../vendor/@openzeppelin/[email protected]/utils/Create2.sol"; import "./Api3ReaderProxyV1.sol"; /// @title Factory contract that deploys Api3ReaderProxyV1 implementations and /// their upgradeable proxies /// @notice The owner of this contract at the time that it deploys a proxy is /// set as the owner of the proxy, which is allowed to upgrade it contract Api3ReaderProxyV1Factory is Ownable, IApi3ReaderProxyV1Factory { /// @notice Api3ServerV1OevExtension contract address address public immutable override api3ServerV1OevExtension; /// @param initialOwner Initial owner /// @param api3ServerV1OevExtension_ Api3ServerV1OevExtension contract /// address constructor( address initialOwner, address api3ServerV1OevExtension_ ) Ownable(initialOwner) { require( api3ServerV1OevExtension_ != address(0), "Api3ServerV1OevExtension address zero" ); api3ServerV1OevExtension = api3ServerV1OevExtension_; } /// @notice Deterministically deploys the Api3ReaderProxyV1 /// @dev As noted in Api3ReaderProxyV1, an implementation is deployed for /// each proxy to be able to use immutable variables /// @param dapiName dAPI name as a bytes32 string /// @param dappId dApp ID /// @param metadata Metadata /// @return proxy Proxy address function deployApi3ReaderProxyV1( bytes32 dapiName, uint256 dappId, bytes calldata metadata ) external override returns (address proxy) { require(dapiName != bytes32(0), "dAPI name zero"); require(dappId != 0, "dApp ID zero"); // The implementation is guaranteed to not have been deployed earlier // if the proxy is not yet deployed. If the proxy is already deployed, // we want to revert anyway. Therefore, there is no need to check the // case where the implementation is already deployed. address implementation = address( new Api3ReaderProxyV1{salt: keccak256(metadata)}( api3ServerV1OevExtension, dapiName, dappId ) ); proxy = address( new ERC1967Proxy{salt: keccak256(metadata)}(implementation, "") ); Api3ReaderProxyV1(proxy).initialize(owner()); emit DeployedApi3ReaderProxyV1(proxy, dapiName, dappId, metadata); } /// @notice Computes the address of the Api3ReaderProxyV1 /// @param dapiName dAPI name as a bytes32 string /// @param dappId dApp ID /// @param metadata Metadata /// @return proxy Proxy address function computeApi3ReaderProxyV1Address( bytes32 dapiName, uint256 dappId, bytes calldata metadata ) external view override returns (address proxy) { require(dapiName != bytes32(0), "dAPI name zero"); require(dappId != 0, "dApp ID zero"); address implementation = Create2.computeAddress( keccak256(metadata), keccak256( abi.encodePacked( type(Api3ReaderProxyV1).creationCode, abi.encode(api3ServerV1OevExtension, dapiName, dappId) ) ) ); proxy = Create2.computeAddress( keccak256(metadata), keccak256( abi.encodePacked( type(ERC1967Proxy).creationCode, abi.encode(implementation, bytes("")) ) ) ); } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../../../interfaces/IApi3ReaderProxy.sol";
interface IApi3ReaderProxyV1 is IApi3ReaderProxy {
error DapiNameIsNotSet();
error DataFeedIsNotInitialized();
error FunctionIsNotSupported();
function initialize(address initialOwner) external;
function api3ServerV1() external returns (address);
function api3ServerV1OevExtension() external returns (address);
function dapiName() external returns (bytes32);
function dappId() external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IApi3ReaderProxyV1Factory {
event DeployedApi3ReaderProxyV1(
address indexed proxy,
bytes32 dapiName,
uint256 dappId,
bytes metadata
);
function deployApi3ReaderProxyV1(
bytes32 dapiName,
uint256 dappId,
bytes calldata metadata
) external returns (address proxy);
function computeApi3ReaderProxyV1Address(
bytes32 dapiName,
uint256 dappId,
bytes calldata metadata
) external view returns (address proxy);
function api3ServerV1OevExtension() external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOevProxy {
function oevBeneficiary() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @dev See DapiProxy.sol for comments about usage
interface IProxy {
function read() external view returns (int224 value, uint32 timestamp);
function api3ServerV1() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Interface of the proxy contract that is used to read a specific API3
/// data feed
/// @notice While reading API3 data feeds, users are strongly recommended to
/// use this interface to interact with data feed-specific proxy contracts,
/// rather than accessing the underlying contracts directly
interface IApi3ReaderProxy {
/// @notice Returns the current value and timestamp of the API3 data feed
/// associated with the proxy contract
/// @dev The user is responsible for validating the returned data. For
/// example, if `value` is the spot price of an asset, it would be
/// reasonable to reject values that are not positive.
/// `timestamp` does not necessarily refer to a timestamp of the chain that
/// the read proxy is deployed on. Considering that it may refer to an
/// off-chain time (such as the system time of the data sources, or the
/// timestamp of another chain), the user should not expect it to be
/// strictly bounded by `block.timestamp`.
/// Considering that the read proxy contract may be upgradeable, the user
/// should not assume any hard guarantees about the behavior in general.
/// For example, even though it may sound reasonable to expect `timestamp`
/// to never decrease over time and the current implementation of the proxy
/// contract guarantees it, technically, an upgrade can cause `timestamp`
/// to decrease. Therefore, the user should be able to handle any change in
/// behavior, which may include reverting gracefully.
/// @return value Data feed value
/// @return timestamp Data feed timestamp
function read() external view returns (int224 value, uint32 timestamp);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IApi3ReaderProxy.sol";
/// @title Mock Api3ReaderProxy contract for local tests
/// @notice MockApi3ReaderProxy acts as an Api3ReaderProxy and allows anyone to
/// mock the data feed value and timestamp it returns. Since it implements no
/// access control, it is only recommended to be used for local tests.
contract MockApi3ReaderProxy is IApi3ReaderProxy {
int224 private _value;
uint32 private _timestamp;
/// @notice Mocks the value and timestamp of the API3 data feed represented
/// by this proxy contract
/// @param value Data feed value
/// @param timestamp Data feed timestamp
function mock(int224 value, uint32 timestamp) external {
require(timestamp != 0, "Timestamp zero");
(_value, _timestamp) = (value, timestamp);
}
/// @notice Returns the mocked value and timestamp of the API3 data feed
/// represented by this proxy contract
/// @dev The real `read()` may revert due to underlying conditions (the
/// respective dAPI name is not set, the respective data feed has not been
/// initalized, etc.) This `read()` implementation reverts if `mock()` has
/// not been called beforehand to simulate such conditions.
/// @return value Data feed value
/// @return timestamp Data feed timestamp
function read()
public
view
override
returns (int224 value, uint32 timestamp)
{
(value, timestamp) = (_value, _timestamp);
require(timestamp != 0, "Data feed not mocked");
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./MockApi3ReaderProxy.sol"; import "../vendor/@chainlink/[email protected]/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol"; /// @title Mock MockApi3ReaderProxyV1 contract for local tests /// @notice MockApi3ReaderProxyV1 is an extension on MockApi3ReaderProxy that /// also implements AggregatorV2V3Interface contract MockApi3ReaderProxyV1 is MockApi3ReaderProxy, AggregatorV2V3Interface { error FunctionIsNotSupported(); /// @dev Refer to Api3ReaderProxyV1 function latestAnswer() external view override returns (int256 value) { (value, ) = read(); } /// @dev Refer to Api3ReaderProxyV1 function latestTimestamp() external view override returns (uint256 timestamp) { (, timestamp) = read(); } /// @dev Refer to Api3ReaderProxyV1 function latestRound() external pure override returns (uint256) { revert FunctionIsNotSupported(); } /// @dev Refer to Api3ReaderProxyV1 function getAnswer(uint256) external pure override returns (int256) { revert FunctionIsNotSupported(); } /// @dev Refer to Api3ReaderProxyV1 function getTimestamp(uint256) external pure override returns (uint256) { revert FunctionIsNotSupported(); } /// @dev Refer to Api3ReaderProxyV1 function decimals() external pure override returns (uint8) { return 18; } /// @dev Refer to Api3ReaderProxyV1 function description() external pure override returns (string memory) { return ""; } /// @dev Refer to Api3ReaderProxyV1 function version() external pure override returns (uint256) { return 4913; } /// @dev Refer to Api3ReaderProxyV1 function getRoundData( uint80 ) external pure override returns (uint80, int256, uint256, uint256, uint80) { revert FunctionIsNotSupported(); } /// @dev Refer to Api3ReaderProxyV1 function latestRoundData() external view override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { roundId = answeredInRound = 0; (answer, startedAt) = read(); updatedAt = startedAt; } }
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;
import "../api3-server-v1/Api3MarketV2.sol";
contract MockApi3MarketV2 is Api3MarketV2 {
constructor(
address owner_,
address proxyFactory_,
uint256 maximumSubscriptionQueueLength_
) Api3MarketV2(owner_, proxyFactory_, maximumSubscriptionQueueLength_) {}
function addSubscriptionToQueue_(
bytes32 dapiName,
bytes32 dataFeedId,
bytes calldata updateParameters,
uint256 duration,
uint256 price
) external {
addSubscriptionToQueue(
dapiName,
dataFeedId,
updateParameters,
duration,
price
);
}
}// SPDX-License-Identifier: MIT pragma solidity 0.8.27; import "../vendor/@openzeppelin/[email protected]/proxy/utils/UUPSUpgradeable.sol"; import "../vendor/@openzeppelin/[email protected]/access/OwnableUpgradeable.sol"; import "../interfaces/IApi3ReaderProxy.sol"; import "../api3-server-v1/interfaces/IApi3ServerV1.sol"; // Mock Api3ReaderProxyV2 contract to test the upgrade mechanism contract MockApi3ReaderProxyV2 is UUPSUpgradeable, OwnableUpgradeable, IApi3ReaderProxy { address public immutable api3ServerV1; bytes32 public immutable dapiName; bytes32 private immutable dapiNameHash; constructor(address api3ServerV1_, bytes32 dapiName_) { api3ServerV1 = api3ServerV1_; dapiName = dapiName_; dapiNameHash = keccak256(abi.encodePacked(dapiName)); _disableInitializers(); } function initialize(address initialOwner) external initializer { __Ownable_init(initialOwner); } function read() public view override returns (int224 value, uint32 timestamp) { (value, timestamp) = IApi3ServerV1(api3ServerV1).dataFeeds( IApi3ServerV1(api3ServerV1).dapiNameHashToDataFeedId(dapiNameHash) ); require(timestamp != 0, "Data feed is not initialized"); } function _authorizeUpgrade( address newImplementation ) internal virtual override onlyOwner {} }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MockCallForwarderTarget {
string public storage1;
uint256 public storage2;
function payableTargetFunction(
string calldata input1,
uint256 input2,
uint256 msgValue
) external payable returns (bytes memory output1, bool output2) {
require(
keccak256(abi.encodePacked(input1)) ==
keccak256(abi.encodePacked("input1")),
"Incorrect input"
);
require(input2 == 123, "Incorrect input");
require(msg.value == msgValue, "Incorrect value");
storage1 = input1;
storage2 = input2;
output1 = hex"12345678";
output2 = true;
}
function nonpayableTargetFunction(
string calldata input1,
uint256 input2
) external returns (bytes memory output1, bool output2) {
require(
keccak256(abi.encodePacked(input1)) ==
keccak256(abi.encodePacked("input1")),
"Incorrect input"
);
require(input2 == 123, "Incorrect input");
storage1 = input1;
storage2 = input2;
output1 = hex"12345678";
output2 = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MockDapiProxyWithOev {
address public immutable api3ServerV1;
bytes32 public immutable dapiNameHash;
address public immutable oevBeneficiary;
constructor(
address _api3ServerV1,
bytes32 _dapiNameHash,
address _oevBeneficiary
) {
api3ServerV1 = _api3ServerV1;
dapiNameHash = _dapiNameHash;
oevBeneficiary = _oevBeneficiary;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract MockMulticallTarget {
error MyError(uint256 fieldAlways123, string fieldAlwaysFoo);
int256[] private _argumentHistory;
function alwaysRevertsWithString(
int256 argPositive,
int256 argNegative
) external pure {
require(argPositive > 0 && argNegative < 0, "Invalid argument");
revert("Reverted with string");
}
function alwaysRevertsWithCustomError(
int256 argPositive,
int256 argNegative
) external pure {
require(argPositive > 0 && argNegative < 0, "Invalid argument");
revert MyError(123, "Foo");
}
function alwaysRevertsWithNoData(
int256 argPositive,
int256 argNegative
) external pure {
require(argPositive > 0 && argNegative < 0, "Invalid argument");
revert(); // solhint-disable-line reason-string
}
function convertsPositiveArgumentToNegative(
int256 argPositive
) external payable returns (int256) {
require(argPositive > 0, "Argument not positive");
_argumentHistory.push(argPositive);
return -argPositive;
}
function argumentHistory() external view returns (int256[] memory) {
int256[] memory argumentHistoryInMemory = new int256[](
_argumentHistory.length
);
for (uint256 ind = 0; ind < _argumentHistory.length; ind++) {
argumentHistoryInMemory[ind] = _argumentHistory[ind];
}
return argumentHistoryInMemory;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../utils/SelfMulticall.sol";
import "./MockMulticallTarget.sol";
contract MockSelfMulticall is SelfMulticall, MockMulticallTarget {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "./SelfMulticall.sol";
import "./interfaces/IExtendedSelfMulticall.sol";
/// @title Contract that extends SelfMulticall to fetch some of the global
/// variables
/// @notice Available global variables are limited to the ones that Airnode
/// tends to need
contract ExtendedSelfMulticall is SelfMulticall, IExtendedSelfMulticall {
/// @notice Returns the chain ID
/// @return Chain ID
function getChainId() external view override returns (uint256) {
return block.chainid;
}
/// @notice Returns the account balance
/// @param account Account address
/// @return Account balance
function getBalance(
address account
) external view override returns (uint256) {
return account.balance;
}
/// @notice Returns if the account contains bytecode
/// @dev An account not containing any bytecode does not indicate that it
/// is an EOA or it will not contain any bytecode in the future.
/// Contract construction and `SELFDESTRUCT` updates the bytecode at the
/// end of the transaction.
/// @return If the account contains bytecode
function containsBytecode(
address account
) external view override returns (bool) {
return account.code.length > 0;
}
/// @notice Returns the current block number
/// @return Current block number
function getBlockNumber() external view override returns (uint256) {
return block.number;
}
/// @notice Returns the current block timestamp
/// @return Current block timestamp
function getBlockTimestamp() external view override returns (uint256) {
return block.timestamp;
}
/// @notice Returns the current block basefee
/// @return Current block basefee
function getBlockBasefee() external view override returns (uint256) {
return block.basefee;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ISelfMulticall.sol";
interface IExtendedSelfMulticall is ISelfMulticall {
function getChainId() external view returns (uint256);
function getBalance(address account) external view returns (uint256);
function containsBytecode(address account) external view returns (bool);
function getBlockNumber() external view returns (uint256);
function getBlockTimestamp() external view returns (uint256);
function getBlockBasefee() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISelfMulticall {
function multicall(
bytes[] calldata data
) external returns (bytes[] memory returndata);
function tryMulticall(
bytes[] calldata data
) external returns (bool[] memory successes, bytes[] memory returndata);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/ISelfMulticall.sol";
/// @title Contract that enables calls to the inheriting contract to be batched
/// @notice Implements two ways of batching, one requires none of the calls to
/// revert and the other tolerates individual calls reverting
/// @dev This implementation uses delegatecall for individual function calls.
/// Since delegatecall is a message call, it can only be made to functions that
/// are externally visible. This means that a contract cannot multicall its own
/// functions that use internal/private visibility modifiers.
/// Refer to OpenZeppelin's Multicall.sol for a similar implementation.
contract SelfMulticall is ISelfMulticall {
/// @notice Batches calls to the inheriting contract and reverts as soon as
/// one of the batched calls reverts
/// @param data Array of calldata of batched calls
/// @return returndata Array of returndata of batched calls
function multicall(
bytes[] calldata data
) external override returns (bytes[] memory returndata) {
uint256 callCount = data.length;
returndata = new bytes[](callCount);
for (uint256 ind = 0; ind < callCount; ) {
bool success;
// solhint-disable-next-line avoid-low-level-calls
(success, returndata[ind]) = address(this).delegatecall(data[ind]);
if (!success) {
bytes memory returndataWithRevertData = returndata[ind];
if (returndataWithRevertData.length > 0) {
// Adapted from OpenZeppelin's Address.sol
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndataWithRevertData)
revert(
add(32, returndataWithRevertData),
returndata_size
)
}
} else {
revert("Multicall: No revert string");
}
}
unchecked {
ind++;
}
}
}
/// @notice Batches calls to the inheriting contract but does not revert if
/// any of the batched calls reverts
/// @param data Array of calldata of batched calls
/// @return successes Array of success conditions of batched calls
/// @return returndata Array of returndata of batched calls
function tryMulticall(
bytes[] calldata data
)
external
override
returns (bool[] memory successes, bytes[] memory returndata)
{
uint256 callCount = data.length;
successes = new bool[](callCount);
returndata = new bytes[](callCount);
for (uint256 ind = 0; ind < callCount; ) {
// solhint-disable-next-line avoid-low-level-calls
(successes[ind], returndata[ind]) = address(this).delegatecall(
data[ind]
);
unchecked {
ind++;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
interface AggregatorInterface {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AggregatorInterface} from "./AggregatorInterface.sol";
import {AggregatorV3Interface} from "./AggregatorV3Interface.sol";
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
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: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "../common/Enum.sol"; /// @title Executor - A contract that can execute transactions /// @author Richard Meissner - <[email protected]> contract Executor { function execute( address to, uint256 value, bytes memory data, Enum.Operation operation, uint256 txGas ) internal returns (bool success) { if (operation == Enum.Operation.DelegateCall) { // solhint-disable-next-line no-inline-assembly assembly { success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) } } else { // solhint-disable-next-line no-inline-assembly assembly { success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) } } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "../common/SelfAuthorized.sol"; /// @title Fallback Manager - A contract that manages fallback calls made to this contract /// @author Richard Meissner - <[email protected]> contract FallbackManager is SelfAuthorized { event ChangedFallbackHandler(address handler); // keccak256("fallback_manager.handler.address") bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5; function internalSetFallbackHandler(address handler) internal { bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT; // solhint-disable-next-line no-inline-assembly assembly { sstore(slot, handler) } } /// @dev Allows to add a contract to handle fallback calls. /// Only fallback calls without value and with data will be forwarded. /// This can only be done via a Safe transaction. /// @param handler contract to handle fallbacks calls. function setFallbackHandler(address handler) public authorized { internalSetFallbackHandler(handler); emit ChangedFallbackHandler(handler); } // solhint-disable-next-line payable-fallback,no-complex-fallback fallback() external { bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT; // solhint-disable-next-line no-inline-assembly assembly { let handler := sload(slot) if iszero(handler) { return(0, 0) } calldatacopy(0, 0, calldatasize()) // The msg.sender address is shifted to the left by 12 bytes to remove the padding // Then the address without padding is stored right after the calldata mstore(calldatasize(), shl(96, caller())) // Add 20 bytes for the address appended add the end let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0) returndatacopy(0, 0, returndatasize()) if iszero(success) { revert(0, returndatasize()) } return(0, returndatasize()) } } }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
interface Guard {
function checkTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures,
address msgSender
) external;
function checkAfterExecution(bytes32 txHash, bool success) external;
}
/// @title Fallback Manager - A contract that manages fallback calls made to this contract
/// @author Richard Meissner - <[email protected]>
contract GuardManager is SelfAuthorized {
event ChangedGuard(address guard);
// keccak256("guard_manager.guard.address")
bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
/// @dev Set a guard that checks transactions before execution
/// @param guard The address of the guard to be used or the 0 address to disable the guard
function setGuard(address guard) external authorized {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, guard)
}
emit ChangedGuard(guard);
}
function getGuard() internal view returns (address guard) {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
guard := sload(slot)
}
}
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "../common/Enum.sol"; import "../common/SelfAuthorized.sol"; import "./Executor.sol"; /// @title Module Manager - A contract that manages modules that can execute transactions via this contract /// @author Stefan George - <[email protected]> /// @author Richard Meissner - <[email protected]> contract ModuleManager is SelfAuthorized, Executor { event EnabledModule(address module); event DisabledModule(address module); event ExecutionFromModuleSuccess(address indexed module); event ExecutionFromModuleFailure(address indexed module); address internal constant SENTINEL_MODULES = address(0x1); mapping(address => address) internal modules; function setupModules(address to, bytes memory data) internal { require(modules[SENTINEL_MODULES] == address(0), "GS100"); modules[SENTINEL_MODULES] = SENTINEL_MODULES; if (to != address(0)) // Setup has to complete successfully or transaction fails. require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), "GS000"); } /// @dev Allows to add a module to the whitelist. /// This can only be done via a Safe transaction. /// @notice Enables the module `module` for the Safe. /// @param module Module to be whitelisted. function enableModule(address module) public authorized { // Module address cannot be null or sentinel. require(module != address(0) && module != SENTINEL_MODULES, "GS101"); // Module cannot be added twice. require(modules[module] == address(0), "GS102"); modules[module] = modules[SENTINEL_MODULES]; modules[SENTINEL_MODULES] = module; emit EnabledModule(module); } /// @dev Allows to remove a module from the whitelist. /// This can only be done via a Safe transaction. /// @notice Disables the module `module` for the Safe. /// @param prevModule Module that pointed to the module to be removed in the linked list /// @param module Module to be removed. function disableModule(address prevModule, address module) public authorized { // Validate module address and check that it corresponds to module index. require(module != address(0) && module != SENTINEL_MODULES, "GS101"); require(modules[prevModule] == module, "GS103"); modules[prevModule] = modules[module]; modules[module] = address(0); emit DisabledModule(module); } /// @dev Allows a Module to execute a Safe transaction without any further confirmations. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction. function execTransactionFromModule( address to, uint256 value, bytes memory data, Enum.Operation operation ) public virtual returns (bool success) { // Only whitelisted modules are allowed. require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104"); // Execute transaction without further confirmations. success = execute(to, value, data, operation, gasleft()); if (success) emit ExecutionFromModuleSuccess(msg.sender); else emit ExecutionFromModuleFailure(msg.sender); } /// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction. function execTransactionFromModuleReturnData( address to, uint256 value, bytes memory data, Enum.Operation operation ) public returns (bool success, bytes memory returnData) { success = execTransactionFromModule(to, value, data, operation); // solhint-disable-next-line no-inline-assembly assembly { // Load free memory location let ptr := mload(0x40) // We allocate memory for the return data by setting the free memory location to // current free memory location + data size + 32 bytes for data size value mstore(0x40, add(ptr, add(returndatasize(), 0x20))) // Store the size mstore(ptr, returndatasize()) // Store the data returndatacopy(add(ptr, 0x20), 0, returndatasize()) // Point the return data to the correct memory location returnData := ptr } } /// @dev Returns if an module is enabled /// @return True if the module is enabled function isModuleEnabled(address module) public view returns (bool) { return SENTINEL_MODULES != module && modules[module] != address(0); } /// @dev Returns array of modules. /// @param start Start of the page. /// @param pageSize Maximum number of modules that should be returned. /// @return array Array of modules. /// @return next Start of the next page. function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) { // Init array with max page size array = new address[](pageSize); // Populate return array uint256 moduleCount = 0; address currentModule = modules[start]; while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) { array[moduleCount] = currentModule; currentModule = modules[currentModule]; moduleCount++; } next = currentModule; // Set correct size of returned array // solhint-disable-next-line no-inline-assembly assembly { mstore(array, moduleCount) } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "../common/SelfAuthorized.sol"; /// @title OwnerManager - Manages a set of owners and a threshold to perform actions. /// @author Stefan George - <[email protected]> /// @author Richard Meissner - <[email protected]> contract OwnerManager is SelfAuthorized { event AddedOwner(address owner); event RemovedOwner(address owner); event ChangedThreshold(uint256 threshold); address internal constant SENTINEL_OWNERS = address(0x1); mapping(address => address) internal owners; uint256 internal ownerCount; uint256 internal threshold; /// @dev Setup function sets initial storage of contract. /// @param _owners List of Safe owners. /// @param _threshold Number of required confirmations for a Safe transaction. function setupOwners(address[] memory _owners, uint256 _threshold) internal { // Threshold can only be 0 at initialization. // Check ensures that setup function can only be called once. require(threshold == 0, "GS200"); // Validate that threshold is smaller than number of added owners. require(_threshold <= _owners.length, "GS201"); // There has to be at least one Safe owner. require(_threshold >= 1, "GS202"); // Initializing Safe owners. address currentOwner = SENTINEL_OWNERS; for (uint256 i = 0; i < _owners.length; i++) { // Owner address cannot be null. address owner = _owners[i]; require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203"); // No duplicate owners allowed. require(owners[owner] == address(0), "GS204"); owners[currentOwner] = owner; currentOwner = owner; } owners[currentOwner] = SENTINEL_OWNERS; ownerCount = _owners.length; threshold = _threshold; } /// @dev Allows to add a new owner to the Safe and update the threshold at the same time. /// This can only be done via a Safe transaction. /// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`. /// @param owner New owner address. /// @param _threshold New threshold. function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized { // Owner address cannot be null, the sentinel or the Safe itself. require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "GS203"); // No duplicate owners allowed. require(owners[owner] == address(0), "GS204"); owners[owner] = owners[SENTINEL_OWNERS]; owners[SENTINEL_OWNERS] = owner; ownerCount++; emit AddedOwner(owner); // Change threshold if threshold was changed. if (threshold != _threshold) changeThreshold(_threshold); } /// @dev Allows to remove an owner from the Safe and update the threshold at the same time. /// This can only be done via a Safe transaction. /// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`. /// @param prevOwner Owner that pointed to the owner to be removed in the linked list /// @param owner Owner address to be removed. /// @param _threshold New threshold. function removeOwner( address prevOwner, address owner, uint256 _threshold ) public authorized { // Only allow to remove an owner, if threshold can still be reached. require(ownerCount - 1 >= _threshold, "GS201"); // Validate owner address and check that it corresponds to owner index. require(owner != address(0) && owner != SENTINEL_OWNERS, "GS203"); require(owners[prevOwner] == owner, "GS205"); owners[prevOwner] = owners[owner]; owners[owner] = address(0); ownerCount--; emit RemovedOwner(owner); // Change threshold if threshold was changed. if (threshold != _threshold) changeThreshold(_threshold); } /// @dev Allows to swap/replace an owner from the Safe with another address. /// This can only be done via a Safe transaction. /// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`. /// @param prevOwner Owner that pointed to the owner to be replaced in the linked list /// @param oldOwner Owner address to be replaced. /// @param newOwner New owner address. function swapOwner( address prevOwner, address oldOwner, address newOwner ) public authorized { // Owner address cannot be null, the sentinel or the Safe itself. require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "GS203"); // No duplicate owners allowed. require(owners[newOwner] == address(0), "GS204"); // Validate oldOwner address and check that it corresponds to owner index. require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "GS203"); require(owners[prevOwner] == oldOwner, "GS205"); owners[newOwner] = owners[oldOwner]; owners[prevOwner] = newOwner; owners[oldOwner] = address(0); emit RemovedOwner(oldOwner); emit AddedOwner(newOwner); } /// @dev Allows to update the number of required confirmations by Safe owners. /// This can only be done via a Safe transaction. /// @notice Changes the threshold of the Safe to `_threshold`. /// @param _threshold New threshold. function changeThreshold(uint256 _threshold) public authorized { // Validate that threshold is smaller than number of owners. require(_threshold <= ownerCount, "GS201"); // There has to be at least one Safe owner. require(_threshold >= 1, "GS202"); threshold = _threshold; emit ChangedThreshold(threshold); } function getThreshold() public view returns (uint256) { return threshold; } function isOwner(address owner) public view returns (bool) { return owner != SENTINEL_OWNERS && owners[owner] != address(0); } /// @dev Returns array of owners. /// @return Array of Safe owners. function getOwners() public view returns (address[] memory) { address[] memory array = new address[](ownerCount); // populate return array uint256 index = 0; address currentOwner = owners[SENTINEL_OWNERS]; while (currentOwner != SENTINEL_OWNERS) { array[index] = currentOwner; currentOwner = owners[currentOwner]; index++; } return array; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title Enum - Collection of enums /// @author Richard Meissner - <[email protected]> contract Enum { enum Operation {Call, DelegateCall} }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments /// @author Richard Meissner - <[email protected]> contract EtherPaymentFallback { event SafeReceived(address indexed sender, uint256 value); /// @dev Fallback function accepts Ether transactions. receive() external payable { emit SafeReceived(msg.sender, msg.value); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title SecuredTokenTransfer - Secure token transfer /// @author Richard Meissner - <[email protected]> contract SecuredTokenTransfer { /// @dev Transfers a token and returns if it was a success /// @param token Token that should be transferred /// @param receiver Receiver to whom the token should be transferred /// @param amount The amount of tokens that should be transferred function transferToken( address token, address receiver, uint256 amount ) internal returns (bool transferred) { // 0xa9059cbb - keccack("transfer(address,uint256)") bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount); // solhint-disable-next-line no-inline-assembly assembly { // We write the return value to scratch space. // See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20) switch returndatasize() case 0 { transferred := success } case 0x20 { transferred := iszero(or(iszero(success), iszero(mload(0)))) } default { transferred := 0 } } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title SelfAuthorized - authorizes current contract to perform actions /// @author Richard Meissner - <[email protected]> contract SelfAuthorized { function requireSelfCall() private view { require(msg.sender == address(this), "GS031"); } modifier authorized() { // This is a function call as it minimized the bytecode size requireSelfCall(); _; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title SignatureDecoder - Decodes signatures that a encoded as bytes /// @author Richard Meissner - <[email protected]> contract SignatureDecoder { /// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`. /// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures /// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access /// @param signatures concatenated rsv signatures function signatureSplit(bytes memory signatures, uint256 pos) internal pure returns ( uint8 v, bytes32 r, bytes32 s ) { // The signature format is a compact form of: // {bytes32 r}{bytes32 s}{uint8 v} // Compact means, uint8 is not padded to 32 bytes. // solhint-disable-next-line no-inline-assembly assembly { let signaturePos := mul(0x41, pos) r := mload(add(signatures, add(signaturePos, 0x20))) s := mload(add(signatures, add(signaturePos, 0x40))) // Here we are loading the last 32 bytes, including 31 bytes // of 's'. There is no 'mload8' to do this. // // 'byte' is not working due to the Solidity parser, so lets // use the second best option, 'and' v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff) } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title Singleton - Base for singleton contracts (should always be first super contract) /// This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`) /// @author Richard Meissner - <[email protected]> contract Singleton { // singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract. // It should also always be ensured that the address is stored alone (uses a full word) address private singleton; }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
/// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
contract StorageAccessible {
/**
* @dev Reads `length` bytes of storage in the currents contract
* @param offset - the offset in the current contract's storage in words to start reading from
* @param length - the number of words (32 bytes) of data to read
* @return the bytes that were read.
*/
function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
bytes memory result = new bytes(length * 32);
for (uint256 index = 0; index < length; index++) {
// solhint-disable-next-line no-inline-assembly
assembly {
let word := sload(add(offset, index))
mstore(add(add(result, 0x20), mul(index, 0x20)), word)
}
}
return result;
}
/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static).
*
* This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
* Specifically, the `returndata` after a call to this method will be:
* `success:bool || response.length:uint256 || response:bytes`.
*
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)
mstore(0x00, success)
mstore(0x20, returndatasize())
returndatacopy(0x40, 0, returndatasize())
revert(0, add(returndatasize(), 0x40))
}
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title GnosisSafeMath
* @dev Math operations with safety checks that revert on error
* Renamed from SafeMath to GnosisSafeMath to avoid conflicts
* TODO: remove once open zeppelin update to solc 0.5.0
*/
library GnosisSafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "./base/ModuleManager.sol"; import "./base/OwnerManager.sol"; import "./base/FallbackManager.sol"; import "./base/GuardManager.sol"; import "./common/EtherPaymentFallback.sol"; import "./common/Singleton.sol"; import "./common/SignatureDecoder.sol"; import "./common/SecuredTokenTransfer.sol"; import "./common/StorageAccessible.sol"; import "./interfaces/ISignatureValidator.sol"; import "./external/GnosisSafeMath.sol"; /// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191. /// @author Stefan George - <[email protected]> /// @author Richard Meissner - <[email protected]> contract GnosisSafe is EtherPaymentFallback, Singleton, ModuleManager, OwnerManager, SignatureDecoder, SecuredTokenTransfer, ISignatureValidatorConstants, FallbackManager, StorageAccessible, GuardManager { using GnosisSafeMath for uint256; string public constant VERSION = "1.3.0"; // keccak256( // "EIP712Domain(uint256 chainId,address verifyingContract)" // ); bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; // keccak256( // "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)" // ); bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8; event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler); event ApproveHash(bytes32 indexed approvedHash, address indexed owner); event SignMsg(bytes32 indexed msgHash); event ExecutionFailure(bytes32 txHash, uint256 payment); event ExecutionSuccess(bytes32 txHash, uint256 payment); uint256 public nonce; bytes32 private _deprecatedDomainSeparator; // Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners mapping(bytes32 => uint256) public signedMessages; // Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners mapping(address => mapping(bytes32 => uint256)) public approvedHashes; // This constructor ensures that this contract can only be used as a master copy for Proxy contracts constructor() { // By setting the threshold it is not possible to call setup anymore, // so we create a Safe with 0 owners and threshold 1. // This is an unusable Safe, perfect for the singleton threshold = 1; } /// @dev Setup function sets initial storage of contract. /// @param _owners List of Safe owners. /// @param _threshold Number of required confirmations for a Safe transaction. /// @param to Contract address for optional delegate call. /// @param data Data payload for optional delegate call. /// @param fallbackHandler Handler for fallback calls to this contract /// @param paymentToken Token that should be used for the payment (0 is ETH) /// @param payment Value that should be paid /// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin) function setup( address[] calldata _owners, uint256 _threshold, address to, bytes calldata data, address fallbackHandler, address paymentToken, uint256 payment, address payable paymentReceiver ) external { // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice setupOwners(_owners, _threshold); if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler); // As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules setupModules(to, data); if (payment > 0) { // To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself) // baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment handlePayment(payment, 0, 1, paymentToken, paymentReceiver); } emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler); } /// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction. /// Note: The fees are always transferred, even if the user transaction fails. /// @param to Destination address of Safe transaction. /// @param value Ether value of Safe transaction. /// @param data Data payload of Safe transaction. /// @param operation Operation type of Safe transaction. /// @param safeTxGas Gas that should be used for the Safe transaction. /// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund) /// @param gasPrice Gas price that should be used for the payment calculation. /// @param gasToken Token address (or 0 if ETH) that is used for the payment. /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v}) function execTransaction( address to, uint256 value, bytes calldata data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address payable refundReceiver, bytes memory signatures ) public payable virtual returns (bool success) { bytes32 txHash; // Use scope here to limit variable lifetime and prevent `stack too deep` errors { bytes memory txHashData = encodeTransactionData( // Transaction info to, value, data, operation, safeTxGas, // Payment info baseGas, gasPrice, gasToken, refundReceiver, // Signature info nonce ); // Increase nonce and execute transaction. nonce++; txHash = keccak256(txHashData); checkSignatures(txHash, txHashData, signatures); } address guard = getGuard(); { if (guard != address(0)) { Guard(guard).checkTransaction( // Transaction info to, value, data, operation, safeTxGas, // Payment info baseGas, gasPrice, gasToken, refundReceiver, // Signature info signatures, msg.sender ); } } // We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500) // We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150 require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, "GS010"); // Use scope here to limit variable lifetime and prevent `stack too deep` errors { uint256 gasUsed = gasleft(); // If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas) // We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas); gasUsed = gasUsed.sub(gasleft()); // If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful // This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert require(success || safeTxGas != 0 || gasPrice != 0, "GS013"); // We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls uint256 payment = 0; if (gasPrice > 0) { payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver); } if (success) emit ExecutionSuccess(txHash, payment); else emit ExecutionFailure(txHash, payment); } { if (guard != address(0)) { Guard(guard).checkAfterExecution(txHash, success); } } } function handlePayment( uint256 gasUsed, uint256 baseGas, uint256 gasPrice, address gasToken, address payable refundReceiver ) private returns (uint256 payment) { // solhint-disable-next-line avoid-tx-origin address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver; if (gasToken == address(0)) { // For ETH we will only adjust the gas price to not be higher than the actual used gas price payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice); require(receiver.send(payment), "GS011"); } else { payment = gasUsed.add(baseGas).mul(gasPrice); require(transferToken(gasToken, receiver, payment), "GS012"); } } /** * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. * @param dataHash Hash of the data (could be either a message hash or transaction hash) * @param data That should be signed (this is passed to an external validator contract) * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash. */ function checkSignatures( bytes32 dataHash, bytes memory data, bytes memory signatures ) public view { // Load threshold to avoid multiple storage loads uint256 _threshold = threshold; // Check that a threshold is set require(_threshold > 0, "GS001"); checkNSignatures(dataHash, data, signatures, _threshold); } /** * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise. * @param dataHash Hash of the data (could be either a message hash or transaction hash) * @param data That should be signed (this is passed to an external validator contract) * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash. * @param requiredSignatures Amount of required valid signatures. */ function checkNSignatures( bytes32 dataHash, bytes memory data, bytes memory signatures, uint256 requiredSignatures ) public view { // Check that the provided signature data is not too short require(signatures.length >= requiredSignatures.mul(65), "GS020"); // There cannot be an owner with address 0. address lastOwner = address(0); address currentOwner; uint8 v; bytes32 r; bytes32 s; uint256 i; for (i = 0; i < requiredSignatures; i++) { (v, r, s) = signatureSplit(signatures, i); if (v == 0) { // If v is 0 then it is a contract signature // When handling contract signatures the address of the contract is encoded into r currentOwner = address(uint160(uint256(r))); // Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes // This check is not completely accurate, since it is possible that more signatures than the threshold are send. // Here we only check that the pointer is not pointing inside the part that is being processed require(uint256(s) >= requiredSignatures.mul(65), "GS021"); // Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes) require(uint256(s).add(32) <= signatures.length, "GS022"); // Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length uint256 contractSignatureLen; // solhint-disable-next-line no-inline-assembly assembly { contractSignatureLen := mload(add(add(signatures, s), 0x20)) } require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023"); // Check signature bytes memory contractSignature; // solhint-disable-next-line no-inline-assembly assembly { // The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s contractSignature := add(add(signatures, s), 0x20) } require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024"); } else if (v == 1) { // If v is 1 then it is an approved hash // When handling approved hashes the address of the approver is encoded into r currentOwner = address(uint160(uint256(r))); // Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, "GS025"); } else if (v > 30) { // If v > 30 then default va (27,28) has been adjusted for eth_sign flow // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover currentOwner = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", dataHash)), v - 4, r, s); } else { // Default is the ecrecover flow with the provided data hash // Use ecrecover with the messageHash for EOA signatures currentOwner = ecrecover(dataHash, v, r, s); } require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "GS026"); lastOwner = currentOwner; } } /// @dev Allows to estimate a Safe transaction. /// This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data. /// Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction` /// @param to Destination address of Safe transaction. /// @param value Ether value of Safe transaction. /// @param data Data payload of Safe transaction. /// @param operation Operation type of Safe transaction. /// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs). /// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version. function requiredTxGas( address to, uint256 value, bytes calldata data, Enum.Operation operation ) external returns (uint256) { uint256 startGas = gasleft(); // We don't provide an error message here, as we use it to return the estimate require(execute(to, value, data, operation, gasleft())); uint256 requiredGas = startGas - gasleft(); // Convert response to string and return via error message revert(string(abi.encodePacked(requiredGas))); } /** * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature. * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract. */ function approveHash(bytes32 hashToApprove) external { require(owners[msg.sender] != address(0), "GS030"); approvedHashes[msg.sender][hashToApprove] = 1; emit ApproveHash(hashToApprove, msg.sender); } /// @dev Returns the chain id used by this contract. function getChainId() public view returns (uint256) { uint256 id; // solhint-disable-next-line no-inline-assembly assembly { id := chainid() } return id; } function domainSeparator() public view returns (bytes32) { return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this)); } /// @dev Returns the bytes that are hashed to be signed by owners. /// @param to Destination address. /// @param value Ether value. /// @param data Data payload. /// @param operation Operation type. /// @param safeTxGas Gas that should be used for the safe transaction. /// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund) /// @param gasPrice Maximum gas price that should be used for this transaction. /// @param gasToken Token address (or 0 if ETH) that is used for the payment. /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). /// @param _nonce Transaction nonce. /// @return Transaction hash bytes. function encodeTransactionData( address to, uint256 value, bytes calldata data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, uint256 _nonce ) public view returns (bytes memory) { bytes32 safeTxHash = keccak256( abi.encode( SAFE_TX_TYPEHASH, to, value, keccak256(data), operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce ) ); return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash); } /// @dev Returns hash to be signed by owners. /// @param to Destination address. /// @param value Ether value. /// @param data Data payload. /// @param operation Operation type. /// @param safeTxGas Fas that should be used for the safe transaction. /// @param baseGas Gas costs for data used to trigger the safe transaction. /// @param gasPrice Maximum gas price that should be used for this transaction. /// @param gasToken Token address (or 0 if ETH) that is used for the payment. /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). /// @param _nonce Transaction nonce. /// @return Transaction hash. function getTransactionHash( address to, uint256 value, bytes calldata data, Enum.Operation operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, uint256 _nonce ) public view returns (bytes32) { return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce)); } }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
contract ISignatureValidatorConstants {
// bytes4(keccak256("isValidSignature(bytes,bytes)")
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
}
abstract contract ISignatureValidator is ISignatureValidatorConstants {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param _data Arbitrary length data signed on the behalf of address(this)
* @param _signature Signature byte array associated with _data
*
* MUST return the bytes4 magic value 0x20c13b0b when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Create2.sol)
pragma solidity ^0.8.0;
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(
uint256 amount,
bytes32 salt,
bytes memory bytecode
) internal returns (address addr) {
require(address(this).balance >= amount, "Create2: insufficient balance");
require(bytecode.length != 0, "Create2: bytecode length is zero");
/// @solidity memory-safe-assembly
assembly {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
}
require(addr != address(0), "Create2: Failed on deploy");
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
* `bytecodeHash` or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
return computeAddress(salt, bytecodeHash, address(this));
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(
bytes32 salt,
bytes32 bytecodeHash,
address deployer
) internal pure returns (address addr) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40) // Get free memory pointer
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |-------------------|---------------------------------------------------------------------------|
// | bytecodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |-------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
mstore(add(ptr, 0x40), bytecodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
mstore8(start, 0xff)
addr := keccak256(start, 85)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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 // Deprecated in v4.8
}
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");
}
}
/**
* @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) {
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.
/// @solidity memory-safe-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 {
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 = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 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 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.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.20;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)
pragma solidity ^0.8.20;
import {Proxy} from "../Proxy.sol";
import {ERC1967Utils} from "./ERC1967Utils.sol";
/**
* @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
* implementation address that can be changed. This address is stored in storage in the location specified by
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
* implementation behind the proxy.
*/
contract ERC1967Proxy is Proxy {
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
*
* If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
* encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
*
* Requirements:
*
* - If `data` is empty, `msg.value` must be zero.
*/
constructor(address implementation, bytes memory _data) payable {
ERC1967Utils.upgradeToAndCall(implementation, _data);
}
/**
* @dev Returns the current implementation address.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/
function _implementation() internal view virtual override returns (address) {
return ERC1967Utils.getImplementation();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)
pragma solidity ^0.8.20;
import {IBeacon} from "../beacon/IBeacon.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*/
library ERC1967Utils {
// We re-declare ERC-1967 events here because they can't be used directly from IERC1967.
// This will be fixed in Solidity 0.8.21. At that point we should remove these events.
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/
error ERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/
error ERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/
error ERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/
error ERC1967NonPayable();
/**
* @dev Returns the current implementation address.
*/
function getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
if (newImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
if (newAdmin == address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/
function changeAdmin(address newAdmin) internal {
emit AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
if (newBeacon.code.length == 0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967NonPayable();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)
pragma solidity ^0.8.20;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback
* function and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable virtual {
_fallback();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.20;
import {IERC1822Proxiable} from "../../interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
_checkNotDelegated();
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC1967-compliant implementation pointing to self.
* See {_onlyProxy}.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Create2.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev Not enough balance for performing a CREATE2 deploy.
*/
error Create2InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev There's no code to deploy.
*/
error Create2EmptyBytecode();
/**
* @dev The deployment failed.
*/
error Create2FailedDeployment();
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
if (address(this).balance < amount) {
revert Create2InsufficientBalance(address(this).balance, amount);
}
if (bytecode.length == 0) {
revert Create2EmptyBytecode();
}
/// @solidity memory-safe-assembly
assembly {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
}
if (addr == address(0)) {
revert Create2FailedDeployment();
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
* `bytecodeHash` or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
return computeAddress(salt, bytecodeHash, address(this));
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40) // Get free memory pointer
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |-------------------|---------------------------------------------------------------------------|
// | bytecodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |-------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
mstore(add(ptr, 0x40), bytecodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
mstore8(start, 0xff)
addr := keccak256(start, 85)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @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
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile 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 {MessageHashUtils-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]
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
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.
/// @solidity memory-safe-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 {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
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]
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
// 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, s);
}
// 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, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @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, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.20;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the Merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates Merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
*@dev The multiproof provided is not valid.
*/
error MerkleProofInvalidMultiproof();
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Sorts the pair (a, b) and hashes the result.
*/
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)
pragma solidity ^0.8.20;
import {Strings} from "../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/
library MessageHashUtils {
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @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.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @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) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(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) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(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) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(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) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(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) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(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) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
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) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
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) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, 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
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, 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
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, 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
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, 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
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, 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
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, 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
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
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_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}{
"optimizer": {
"enabled": true,
"runs": 1000
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"api3ReaderProxyV1Factory_","type":"address"},{"internalType":"uint256","name":"maximumSubscriptionQueueLength_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"subscriptionId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"dataFeedId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sponsorWallet","type":"address"},{"indexed":false,"internalType":"bytes","name":"updateParameters","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paymentAmount","type":"uint256"}],"name":"BoughtSubscription","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dapiName","type":"bytes32"}],"name":"CanceledSubscriptions","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hashType","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"hashValue","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"hashTimestamp","type":"uint256"}],"name":"RegisteredHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"airseekerRegistry","type":"address"}],"name":"SetAirseekerRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hashType","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"hashValue","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"hashTimestamp","type":"uint256"}],"name":"SetHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hashType","type":"bytes32"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"}],"name":"SetSigners","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"subscriptionId","type":"bytes32"}],"name":"UpdatedCurrentSubscriptionId","type":"event"},{"inputs":[],"name":"DAPI_MANAGEMENT_MERKLE_ROOT_HASH_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAPI_PRICING_MERKLE_ROOT_HASH_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAXIMUM_DAPI_UPDATE_AGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNED_API_URL_MERKLE_ROOT_HASH_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"airseekerRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"api3ReaderProxyV1Factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"api3ServerV1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"},{"internalType":"address payable","name":"sponsorWallet","type":"address"},{"internalType":"bytes","name":"updateParameters","type":"bytes"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bytes","name":"dapiManagementAndDapiPricingMerkleData","type":"bytes"}],"name":"buySubscription","outputs":[{"internalType":"bytes32","name":"subscriptionId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"}],"name":"cancelSubscriptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"}],"name":"computeExpectedSponsorWalletBalance","outputs":[{"internalType":"uint256","name":"expectedSponsorWalletBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"bytes","name":"updateParameters","type":"bytes"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"computeExpectedSponsorWalletBalanceAfterSubscriptionIsAdded","outputs":[{"internalType":"uint256","name":"expectedSponsorWalletBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"containsBytecode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"dapiNameToCurrentSubscriptionId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"uint256","name":"dappId","type":"uint256"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"deployApi3ReaderProxyV1","outputs":[{"internalType":"address","name":"api3ReaderProxyV1","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockBasefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"}],"name":"getDapiData","outputs":[{"internalType":"bytes","name":"dataFeedDetails","type":"bytes"},{"internalType":"int224","name":"dapiValue","type":"int224"},{"internalType":"uint32","name":"dapiTimestamp","type":"uint32"},{"internalType":"int224[]","name":"beaconValues","type":"int224[]"},{"internalType":"uint32[]","name":"beaconTimestamps","type":"uint32[]"},{"internalType":"bytes[]","name":"updateParameters","type":"bytes[]"},{"internalType":"uint32[]","name":"endTimestamps","type":"uint32[]"},{"internalType":"uint224[]","name":"dailyPrices","type":"uint224[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"}],"name":"getDataFeedData","outputs":[{"internalType":"bytes","name":"dataFeedDetails","type":"bytes"},{"internalType":"int224","name":"dataFeedValue","type":"int224"},{"internalType":"uint32","name":"dataFeedTimestamp","type":"uint32"},{"internalType":"int224[]","name":"beaconValues","type":"int224[]"},{"internalType":"uint32[]","name":"beaconTimestamps","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashType","type":"bytes32"}],"name":"getHashValue","outputs":[{"internalType":"bytes32","name":"hashValue","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hashTypeToSignersHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hashes","outputs":[{"internalType":"bytes32","name":"value","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumSubscriptionQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"returndata","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"multicallData","type":"bytes[]"},{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"},{"internalType":"address payable","name":"sponsorWallet","type":"address"},{"internalType":"bytes","name":"updateParameters","type":"bytes"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bytes","name":"dapiManagementAndDapiPricingMerkleData","type":"bytes"}],"name":"multicallAndBuySubscription","outputs":[{"internalType":"bytes[]","name":"returndata","type":"bytes[]"},{"internalType":"bytes32","name":"subscriptionId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"dataFeedDetails","type":"bytes"}],"name":"registerDataFeed","outputs":[{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashType","type":"bytes32"},{"internalType":"bytes32","name":"hashValue","type":"bytes32"},{"internalType":"uint256","name":"hashTimestamp","type":"uint256"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"registerHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"airseekerRegistry_","type":"address"}],"name":"setAirseekerRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashType","type":"bytes32"},{"internalType":"bytes32","name":"hashValue","type":"bytes32"}],"name":"setHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashType","type":"bytes32"},{"internalType":"address[]","name":"signers","type":"address[]"}],"name":"setSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signatureDelegationHashType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"subscriptionId","type":"bytes32"}],"name":"subscriptionIdToUpdateParameters","outputs":[{"internalType":"bytes","name":"updateParameters","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"subscriptions","outputs":[{"internalType":"bytes32","name":"updateParametersHash","type":"bytes32"},{"internalType":"uint32","name":"endTimestamp","type":"uint32"},{"internalType":"uint224","name":"dailyPrice","type":"uint224"},{"internalType":"bytes32","name":"nextSubscriptionId","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"tryMulticall","outputs":[{"internalType":"bool[]","name":"successes","type":"bool[]"},{"internalType":"bytes[]","name":"returndata","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"tryMulticallData","type":"bytes[]"},{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"},{"internalType":"address payable","name":"sponsorWallet","type":"address"},{"internalType":"bytes","name":"updateParameters","type":"bytes"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bytes","name":"dapiManagementAndDapiPricingMerkleData","type":"bytes"}],"name":"tryMulticallAndBuySubscription","outputs":[{"internalType":"bool[]","name":"successes","type":"bool[]"},{"internalType":"bytes[]","name":"returndata","type":"bytes[]"},{"internalType":"bytes32","name":"subscriptionId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"beaconIds","type":"bytes32[]"}],"name":"updateBeaconSetWithBeacons","outputs":[{"internalType":"bytes32","name":"beaconSetId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"airnode","type":"address"},{"internalType":"bytes32","name":"templateId","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateBeaconWithSignedData","outputs":[{"internalType":"bytes32","name":"beaconId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"}],"name":"updateCurrentSubscriptionId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dapiName","type":"bytes32"},{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"},{"internalType":"address","name":"sponsorWallet","type":"address"},{"internalType":"bytes","name":"dapiManagementMerkleData","type":"bytes"}],"name":"updateDapiName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"airnode","type":"address"},{"internalType":"string","name":"signedApiUrl","type":"string"},{"internalType":"bytes","name":"signedApiUrlMerkleData","type":"bytes"}],"name":"updateSignedApiUrl","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e060405234801561001057600080fd5b50604051615da4380380615da483398101604081905261002f9161020f565b82806001600160a01b03811661006057604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610069816101a3565b5050806000036100bb5760405162461bcd60e51b815260206004820152601960248201527f4d6178696d756d207175657565206c656e677468207a65726f000000000000006044820152606401610057565b6001600160a01b03821660a08190526040805163ce7ebd6d60e01b8152905163ce7ebd6d9160048082019260209290919082900301816000875af1158015610107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012b919061024b565b6001600160a01b0316632d6a744e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061018c919061024b565b6001600160a01b031660805260c0525061026d9050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461020a57600080fd5b919050565b60008060006060848603121561022457600080fd5b61022d846101f3565b925061023b602085016101f3565b9150604084015190509250925092565b60006020828403121561025d57600080fd5b610266826101f3565b9392505050565b60805160a05160c051615aad6102f7600039600081816107340152613c030152600081816104b40152612360015260008181610440015281816109d901528181610fb2015281816123f8015281816128b10152818161298f01528181612b7901528181612df401528181612f26015281816138c50152818161399c0152613dc50152615aad6000f3fe6080604052600436106102f15760003560e01c8063715018a61161018f578063b7afd507116100e1578063d7fa10071161008a578063f2fde38b11610064578063f2fde38b1461093f578063f8b2cb4f1461095f578063fa0130671461098757600080fd5b8063d7fa1007146108d7578063d8d2f90f146108f7578063e637cf001461092857600080fd5b8063c6c04e16116100bb578063c6c04e1614610845578063d5659f3114610879578063d658d2e91461088e57600080fd5b8063b7afd507146107f2578063c1516e5414610805578063c30027601461082557600080fd5b806394259c6c11610143578063a89307b41161011d578063a89307b414610776578063aa2b44e414610798578063ac9650d8146107c557600080fd5b806394259c6c1461069957806397f679d314610722578063a5f36cb11461075657600080fd5b8063845ebe4311610174578063845ebe43146106215780638c9f4c791461064e5780638da5cb5b1461067b57600080fd5b8063715018a6146105f9578063796b89b91461060e57600080fd5b80633adb35fe116102485780634dcc19fe116101fc5780635989eaeb116101d65780635989eaeb1461057f5780635d868194146105b957806364c2359d146105d957600080fd5b80634dcc19fe1461053757806353130e261461054a5780635885c7711461056a57600080fd5b806342cbb15c1161022d57806342cbb15c146104d6578063437b9116146104e95780634dc610d41461051757600080fd5b80633adb35fe1461048d5780633db35663146104a257600080fd5b80631a0a0b3e116102aa578063288ddb6111610284578063288ddb61146104195780632d6a744e1461042e5780633408e4701461047a57600080fd5b80631a0a0b3e146103b85780631b1f24d8146103d85780631d911b6d146103f957600080fd5b8063044c9bd7116102db578063044c9bd71461034b5780630b62ebf21461037857806318d6e2d41461039857600080fd5b8062aae33f146102f65780630141ff4814610329575b600080fd5b34801561030257600080fd5b50610316610311366004614456565b6109a7565b6040519081526020015b60405180910390f35b34801561033557600080fd5b50610349610344366004614498565b610a5b565b005b34801561035757600080fd5b50610316610366366004614498565b60009081526001602052604090205490565b34801561038457600080fd5b506103496103933660046144c9565b610b33565b3480156103a457600080fd5b506103496103b33660046144e6565b610d18565b3480156103c457600080fd5b506103166103d3366004614574565b610f7f565b6103eb6103e636600461461f565b611042565b6040516103209291906147ac565b34801561040557600080fd5b506103496104143660046147ce565b6110e0565b34801561042557600080fd5b5061031661129a565b34801561043a57600080fd5b506104627f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610320565b34801561048657600080fd5b5046610316565b34801561049957600080fd5b506103166112e0565b3480156104ae57600080fd5b506104627f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e257600080fd5b5043610316565b3480156104f557600080fd5b50610509610504366004614456565b611356565b604051610320929190614894565b34801561052357600080fd5b50610349610532366004614498565b6114bc565b34801561054357600080fd5b5048610316565b34801561055657600080fd5b50600354610462906001600160a01b031681565b34801561057657600080fd5b506103166115bd565b34801561058b57600080fd5b506105a961059a3660046144c9565b6001600160a01b03163b151590565b6040519015158152602001610320565b3480156105c557600080fd5b506103166105d43660046148b9565b6115ee565b3480156105e557600080fd5b506103166105f4366004614498565b61163a565b34801561060557600080fd5b506103496116f0565b34801561061a57600080fd5b5042610316565b34801561062d57600080fd5b5061031661063c366004614498565b60026020526000908152604090205481565b34801561065a57600080fd5b5061066e610669366004614498565b611738565b60405161032091906148ef565b34801561068757600080fd5b506000546001600160a01b0316610462565b3480156106a557600080fd5b506106ef6106b4366004614498565b600460205260009081526040902080546001820154600290920154909163ffffffff8116916401000000009091046001600160e01b03169084565b6040805194855263ffffffff90931660208501526001600160e01b03909116918301919091526060820152608001610320565b34801561072e57600080fd5b506103167f000000000000000000000000000000000000000000000000000000000000000081565b34801561076257600080fd5b50610349610771366004614902565b6117e7565b61078961078436600461461f565b611d2f565b60405161032093929190614952565b3480156107a457600080fd5b506103166107b3366004614498565b60056020526000908152604090205481565b3480156107d157600080fd5b506107e56107e0366004614456565b611dd2565b6040516103209190614988565b61031661080036600461499b565b611f53565b34801561081157600080fd5b50610316610820366004614a4b565b612181565b34801561083157600080fd5b50610462610840366004614aa9565b61232d565b34801561085157600080fd5b50610865610860366004614498565b6123e7565b604051610320989796959493929190614b69565b34801561088557600080fd5b50610316612762565b34801561089a57600080fd5b506108c26108a9366004614498565b6001602081905260009182526040909120805491015482565b60408051928352602083019190915201610320565b3480156108e357600080fd5b506103496108f2366004614c35565b612793565b34801561090357600080fd5b50610917610912366004614498565b612804565b604051610320959493929190614c57565b34801561093457600080fd5b506103166201518081565b34801561094b57600080fd5b5061034961095a3660046144c9565b612ce3565b34801561096b57600080fd5b5061031661097a3660046144c9565b6001600160a01b03163190565b34801561099357600080fd5b506103496109a2366004614ca5565b612d2b565b6040517eaae33f0000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169062aae33f90610a0f9086908690600401614cf2565b6020604051808303816000875af1158015610a2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a529190614d44565b90505b92915050565b60008181526005602052604090205480610abc5760405162461bcd60e51b815260206004820152601860248201527f537562736372697074696f6e20717565756520656d707479000000000000000060448201526064015b60405180910390fd5b6000818152600460205260409020600101544263ffffffff9091161115610b255760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420737562736372697074696f6e206e6f7420656e64656400006044820152606401610ab3565b610b2f8282612f92565b5050565b610b3b6130af565b6001600160a01b038116610b915760405162461bcd60e51b815260206004820152601e60248201527f4169727365656b657252656769737472792061646472657373207a65726f00006044820152606401610ab3565b6003546001600160a01b031615610bea5760405162461bcd60e51b815260206004820152601d60248201527f4169727365656b6572526567697374727920616c7265616479207365740000006044820152606401610ab3565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c569190614d5d565b6001600160a01b031614610cac5760405162461bcd60e51b815260206004820152601b60248201527f4e6f74204169727365656b65725265676973747279206f776e657200000000006044820152606401610ab3565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f90f2d5c680e476ebdec8de98d28cd387630163236f0975752747b4075c8300f89060200160405180910390a150565b610d206130af565b82610d6d5760405162461bcd60e51b815260206004820152600e60248201527f486173682074797065207a65726f0000000000000000000000000000000000006044820152606401610ab3565b806000819003610dbf5760405162461bcd60e51b815260206004820152600d60248201527f5369676e65727320656d707479000000000000000000000000000000000000006044820152606401610ab3565b600083838281610dd157610dd1614d7a565b9050602002016020810190610de691906144c9565b6001600160a01b031603610e3c5760405162461bcd60e51b815260206004820152601960248201527f4669727374207369676e65722061646472657373207a65726f000000000000006044820152606401610ab3565b60015b81811015610f06578383610e54600184614da6565b818110610e6357610e63614d7a565b9050602002016020810190610e7891906144c9565b6001600160a01b0316848483818110610e9357610e93614d7a565b9050602002016020810190610ea891906144c9565b6001600160a01b031611610efe5760405162461bcd60e51b815260206004820152601e60248201527f5369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610ab3565b600101610e3f565b508282604051602001610f1a929190614db9565b60408051601f198184030181528282528051602091820120600088815260029092529190205584907f5a1f5ee4ceedd78b1982374b4790e8aa9f31e8af1c32aaef46b2afd8a789193a90610f719086908690614dfb565b60405180910390a250505050565b6040517f1a0a0b3e0000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631a0a0b3e90610ff3908b908b908b908b908b908b908b90600401614e71565b6020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110369190614d44565b98975050505050505050565b60606000306001600160a01b031663ac9650d88e8e6040518363ffffffff1660e01b8152600401611074929190614ec1565b6000604051808303816000875af1158015611093573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110bb91908101906150cf565b91506110ce8b8b8b8b8b8b8b8b8b611f53565b90509b509b9950505050505050505050565b6110ed8585858585613106565b6003546040517f085df6ab0000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301529091169063085df6ab90602401600060405180830381865afa158015611150573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111789190810190615104565b604051602001611188919061514d565b6040516020818303038152906040528051906020012084846040516020016111b1929190615169565b60405160208183030381529060405280519060200120036112145760405162461bcd60e51b815260206004820152601e60248201527f446f6573206e6f7420757064617465207369676e6564204150492055524c00006044820152606401610ab3565b6003546040517ffba8f22f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063fba8f22f9061126190889088908890600401615179565b600060405180830381600087803b15801561127b57600080fd5b505af115801561128f573d6000803e3d6000fd5b505050505050505050565b6040517f644150492070726963696e67204d65726b6c6520726f6f74000000000000000060208201526038015b6040516020818303038152906040528051906020012081565b600060405160200161133b907f417069334d61726b65745632207369676e61747572652064656c65676174696f81527f6e00000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405280519060200120905090565b606080828067ffffffffffffffff81111561137357611373614f64565b60405190808252806020026020018201604052801561139c578160200160208202803683370190505b5092508067ffffffffffffffff8111156113b8576113b8614f64565b6040519080825280602002602001820160405280156113eb57816020015b60608152602001906001900390816113d65790505b50915060005b818110156114b3573086868381811061140c5761140c614d7a565b905060200281019061141e919061519c565b60405161142c929190615169565b600060405180830381855af49150503d8060008114611467576040519150601f19603f3d011682016040523d82523d6000602084013e61146c565b606091505b5085838151811061147f5761147f614d7a565b6020026020010185848151811061149857611498614d7a565b602090810291909101019190915290151590526001016113f1565b50509250929050565b6114c46130af565b60008181526005602052604090205461151f5760405162461bcd60e51b815260206004820152601860248201527f537562736372697074696f6e20717565756520656d70747900000000000000006044820152606401610ab3565b600081815260056020526040808220919091556003549051632412a9cb60e01b8152600481018390526001600160a01b0390911690632412a9cb90602401600060405180830381600087803b15801561157757600080fd5b505af115801561158b573d6000803e3d6000fd5b50506040518392507f07731f198aeecb61ff6de517fa82a003ba1bb3846140b23b62d7563dc2ddfb6a9150600090a250565b6040517f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000006020820152603b016112c7565b6003546040517f5d8681940000000000000000000000000000000000000000000000000000000081526000916001600160a01b031690635d86819490610a0f90869086906004016151e3565b6000806116464261324c565b600084815260056020526040812054919250905b80156116e8576000818152600460205260409020600181015490925063ffffffff16428111156116dc576001830154620151809064010000000090046001600160e01b03166116a986846151f7565b63ffffffff166116b99190615213565b6116c39190615261565b6116d6906001600160e01b03168661528f565b94508093505b5050600281015461165a565b505050919050565b60405162461bcd60e51b815260206004820152601d60248201527f4f776e6572736869702063616e6e6f742062652072656e6f756e6365640000006044820152606401610ab3565b600081815260046020908152604080832054835260069091529020805460609190611762906152a2565b80601f016020809104026020016040519081016040528092919081815260200182805461178e906152a2565b80156117db5780601f106117b0576101008083540402835291602001916117db565b820191906000526020600020905b8154815290600101906020018083116117be57829003601f168201915b50505050509050919050565b836118345760405162461bcd60e51b815260206004820152600f60248201527f486173682076616c7565207a65726f00000000000000000000000000000000006044820152606401610ab3565b428311156118845760405162461bcd60e51b815260206004820152601a60248201527f486173682074696d657374616d702066726f6d206675747572650000000000006044820152606401610ab3565b6000858152600160208190526040909120015483116118e55760405162461bcd60e51b815260206004820152601e60248201527f486173682074696d657374616d70206e6f74206d6f726520726563656e7400006044820152606401610ab3565b600085815260026020526040902054806119415760405162461bcd60e51b815260206004820152600f60248201527f5369676e657273206e6f742073657400000000000000000000000000000000006044820152606401610ab3565b8160008167ffffffffffffffff81111561195d5761195d614f64565b604051908082528060200260200182016040528015611986578160200160208202803683370190505b5060408051602081018b9052908101899052606081018890529091506000906119f6906080015b604051602081830303815290604052805190602001207f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060005b83811015611c41576000878783818110611a1757611a17614d7a565b9050602002810190611a29919061519c565b9150506040198101611ace57611a9783898985818110611a4b57611a4b614d7a565b9050602002810190611a5d919061519c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061328192505050565b848381518110611aa957611aa9614d7a565b60200260200101906001600160a01b031690816001600160a01b031681525050611c38565b6101608103611bf05760008060008a8a86818110611aee57611aee614d7a565b9050602002810190611b00919061519c565b810190611b0d919061532d565b925092509250824210611b625760405162461bcd60e51b815260206004820152601060248201527f44656c65676174696f6e20656e646564000000000000000000000000000000006044820152606401610ab3565b611bb6611bb0611b706112e0565b611b7a8985613281565b866040516020016119ad9392919092835260609190911b6bffffffffffffffffffffffff19166020830152603482015260540190565b83613281565b878681518110611bc857611bc8614d7a565b60200260200101906001600160a01b031690816001600160a01b031681525050505050611c38565b60405162461bcd60e51b815260206004820152601860248201527f496e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610ab3565b506001016119fb565b5081604051602001611c53919061539f565b604051602081830303815290604052805190602001208414611cb75760405162461bcd60e51b815260206004820152601260248201527f5369676e6174757265206d69736d6174636800000000000000000000000000006044820152606401610ab3565b60408051808201825289815260208082018a815260008d815260019283905284902092518355519101555189907fa33e8931ee2a869317bbe04201dab2907fd39d2d7f014c15b8459986e62c279190611d1c908b908b90918252602082015260400190565b60405180910390a2505050505050505050565b6060806000306001600160a01b031663437b91168f8f6040518363ffffffff1660e01b8152600401611d62929190614ec1565b6000604051808303816000875af1158015611d81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da991908101906153ee565b9093509150611dbf8c8c8c8c8c8c8c8c8c611f53565b90509b509b509b98505050505050505050565b6060818067ffffffffffffffff811115611dee57611dee614f64565b604051908082528060200260200182016040528015611e2157816020015b6060815260200190600190039081611e0c5790505b50915060005b81811015611f4b57600030868684818110611e4457611e44614d7a565b9050602002810190611e56919061519c565b604051611e64929190615169565b600060405180830381855af49150503d8060008114611e9f576040519150601f19603f3d011682016040523d82523d6000602084013e611ea4565b606091505b50858481518110611eb757611eb7614d7a565b6020908102919091010152905080611f42576000848381518110611edd57611edd614d7a565b60200260200101519050600081511115611efa5780518082602001fd5b60405162461bcd60e51b815260206004820152601b60248201527f4d756c746963616c6c3a204e6f2072657665727420737472696e6700000000006044820152606401610ab3565b50600101611e27565b505092915050565b600088611fa25760405162461bcd60e51b815260206004820152601160248201527f446174612066656564204944207a65726f0000000000000000000000000000006044820152606401610ab3565b6001600160a01b038816611ff85760405162461bcd60e51b815260206004820152601b60248201527f53706f6e736f722077616c6c65742061646472657373207a65726f00000000006044820152606401610ab3565b6120098a8a8a8a8a8a8a8a8a6132ab565b6120178a8a89898989613610565b90506120228a61163a565b612036346001600160a01b038b163161528f565b10156120845760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e74207061796d656e740000000000000000000000006044820152606401610ab3565b808a7fd44e8abecc305a9434d27a049c731a8331cee8bca6496154f47835b396ce55068b8b8b8b8b8b346040516120c197969594939291906154b9565b60405180910390a33415612174576000886001600160a01b03163460405160006040518083038185875af1925050503d806000811461211c576040519150601f19603f3d011682016040523d82523d6000602084013e612121565b606091505b50509050806121725760405162461bcd60e51b815260206004820152601560248201527f5472616e7366657220756e7375636365737366756c00000000000000000000006044820152606401610ab3565b505b9998505050505050505050565b6000606084146121d35760405162461bcd60e51b815260206004820181905260248201527f55706461746520706172616d6574657273206c656e67746820696e76616c69646044820152606401610ab3565b6000806000806121e58a8a8a8a613a0f565b935093509350935060008787620151806121ff9190615501565b6122099190615518565b905060006122164261324c565b9050600084156122345760008d815260056020526040902054612236565b865b90505b801561231d5786810361228657620151808361225584896151f7565b63ffffffff166122659190615501565b61226f9190615518565b612279908961528f565b9750859150839050612239565b6000818152600460205260409020600181015463ffffffff16428111156122ff576001820154620151809064010000000090046001600160e01b03166122cc86846151f7565b63ffffffff166122dc9190615213565b6122e69190615261565b6122f9906001600160e01b03168b61528f565b99508093505b82870361230e57889250612316565b816002015492505b5050612239565b5050505050505095945050505050565b6040517fc30027600000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c30027609061239b90889088908890889060040161552c565b6020604051808303816000875af11580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190614d5d565b95945050505050565b6060600080606080606080606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663472c22f18b60405160200161243891815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161246c91815260200190565b602060405180830381865afa158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190614d44565b90506124b881612804565b60008f815260056020526040812054959e50939c50919a5098509650905b801561250357816124e681615556565b600092835260046020526040909220600201549192506124d69050565b508067ffffffffffffffff81111561251d5761251d614f64565b60405190808252806020026020018201604052801561255057816020015b606081526020019060019003908161253b5790505b5094508067ffffffffffffffff81111561256c5761256c614f64565b604051908082528060200260200182016040528015612595578160200160208202803683370190505b5093508067ffffffffffffffff8111156125b1576125b1614f64565b6040519080825280602002602001820160405280156125da578160200160208202803683370190505b5060008c8152600560209081526040808320548352600490915281209194505b828110156127535781546000908152600660205260409020805461261d906152a2565b80601f0160208091040260200160405190810160405280929190818152602001828054612649906152a2565b80156126965780601f1061266b57610100808354040283529160200191612696565b820191906000526020600020905b81548152906001019060200180831161267957829003601f168201915b50505050508782815181106126ad576126ad614d7a565b60209081029190910101526001820154865163ffffffff909116908790839081106126da576126da614d7a565b602002602001019063ffffffff16908163ffffffff16815250508160010160049054906101000a90046001600160e01b031685828151811061271e5761271e614d7a565b6001600160e01b03909216602092830291909101820152600290920154600090815260049092526040909120906001016125fa565b50505050919395975091939597565b6040517f5369676e6564204150492055524c204d65726b6c6520726f6f740000000000006020820152603a016112c7565b61279b6130af565b604080518082018252828152426020808301828152600087815260018084529086902094518555905193019290925582518481529182015283917f19cb5bc6996c2541fb44252778e9c8c952662cce4670a75a4174b50c765bd7d1910160405180910390a25050565b6003546040517f6e85b69a000000000000000000000000000000000000000000000000000000008152600481018390526060916000918291849182916001600160a01b031690636e85b69a90602401600060405180830381865afa158015612870573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612898919081019061556f565b6040516367a7cfb760e01b8152600481018890529095507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906367a7cfb7906024016040805180830381865afa1580156128ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292391906155b3565b86519195509350603f1901612abd57604080516001808252818301909252906020808301908036833750506040805160018082528183019092529294509050602080830190803683370190505090506000808680602001905181019061298991906155f6565b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166367a7cfb7612a0884846040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6040518263ffffffff1660e01b8152600401612a2691815260200190565b6040805180830381865afa158015612a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6691906155b3565b85600081518110612a7957612a79614d7a565b6020026020010185600081518110612a9357612a93614d7a565b602002602001018263ffffffff1663ffffffff1681525082601b0b601b0b81525050505050612cda565b845115612cda5760008086806020019051810190612adb9190615682565b815191935091508067ffffffffffffffff811115612afb57612afb614f64565b604051908082528060200260200182016040528015612b24578160200160208202803683370190505b5094508067ffffffffffffffff811115612b4057612b40614f64565b604051908082528060200260200182016040528015612b69578160200160208202803683370190505b50935060005b81811015612cd5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166367a7cfb7612c24868481518110612bbb57612bbb614d7a565b6020026020010151868581518110612bd557612bd5614d7a565b60200260200101516040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6040518263ffffffff1660e01b8152600401612c4291815260200190565b6040805180830381865afa158015612c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8291906155b3565b878381518110612c9457612c94614d7a565b60200260200101878481518110612cad57612cad614d7a565b63ffffffff90931660209384029190910190920191909152601b9190910b9052600101612b6f565b505050505b91939590929450565b60405162461bcd60e51b815260206004820152601f60248201527f4f776e6572736869702063616e6e6f74206265207472616e73666572726564006044820152606401610ab3565b8315612d8c576001600160a01b038316612d875760405162461bcd60e51b815260206004820152601b60248201527f53706f6e736f722077616c6c65742061646472657373207a65726f00000000006044820152606401610ab3565b612de3565b6001600160a01b03831615612de35760405162461bcd60e51b815260206004820152601f60248201527f53706f6e736f722077616c6c65742061646472657373206e6f74207a65726f006044820152606401610ab3565b612df08585858585613c80565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663472c22f187604051602001612e3491815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401612e6891815260200190565b602060405180830381865afa158015612e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea99190614d44565b9050848103612efa5760405162461bcd60e51b815260206004820152601960248201527f446f6573206e6f74207570646174652064415049206e616d65000000000000006044820152606401610ab3565b8415612f0957612f0985613dac565b6040516391eed08560e01b815260048101879052602481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391eed08590604401600060405180830381600087803b158015612f7257600080fd5b505af1158015612f86573d6000803e3d6000fd5b50505050505050505050565b5b6000908152600460205260409020600201548015801590612fcd57506000818152600460205260409020600101544263ffffffff90911611155b612f9357604051819083907fe08aff0930a0c84c077d2ce7e690a3f910c0f8705376b2405816efb89b9869b790600090a360008281526005602052604090208190558061307757600354604051632412a9cb60e01b8152600481018490526001600160a01b0390911690632412a9cb906024015b600060405180830381600087803b15801561305b57600080fd5b505af115801561306f573d6000803e3d6000fd5b505050505050565b6003546001600160a01b031663d23bab148361309284611738565b6040518363ffffffff1660e01b8152600401613041929190615745565b336130c26000546001600160a01b031690565b6001600160a01b031614613104576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ab3565b565b600080613115838501856157bc565b915091508160016000604051602001613151907f5369676e6564204150492055524c204d65726b6c6520726f6f740000000000008152601a0190565b60405160208183030381529060405280519060200120815260200190815260200160002060000154146131b55760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b61320781838989896040516020016131cf93929190615179565b60408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120613f6f565b6132435760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b50505050505050565b600063ffffffff82111561327d576040516306dfcc6560e41b81526020600482015260248101839052604401610ab3565b5090565b6000806000806132918686613f87565b9250925092506132a18282613fd4565b5090949350505050565b886132f85760405162461bcd60e51b815260206004820152600e60248201527f64415049206e616d65207a65726f0000000000000000000000000000000000006044820152606401610ab3565b606085146133485760405162461bcd60e51b815260206004820181905260248201527f55706461746520706172616d6574657273206c656e67746820696e76616c69646044820152606401610ab3565b836000036133985760405162461bcd60e51b815260206004820152600d60248201527f4475726174696f6e207a65726f000000000000000000000000000000000000006044820152606401610ab3565b826000036133e85760405162461bcd60e51b815260206004820152600a60248201527f5072696365207a65726f000000000000000000000000000000000000000000006044820152606401610ab3565b60008080806133f9858701876157f9565b93509350935093508360016000604051602001613439907f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000008152601b0190565b604051602081830303815290604052805190602001208152602001908152602001600020600001541461349d5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b60408051602081018f90529081018d90526001600160a01b038c1660608201526134cd90849086906080016131cf565b6135095760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b8160016000604051602001613541907f644150492070726963696e67204d65726b6c6520726f6f740000000000000000815260180190565b60405160208183030381529060405280519060200120815260200190815260200160002060000154146135a55760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b6135c581838f468e8e8e8e6040516020016131cf96959493929190615875565b6136015760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b50505050505050505050505050565b6000806000806136228a898989613a0f565b6040519397509195509350915060009061363f908a908a90615169565b60405180910390209050600660008281526020019081526020016000208054613667906152a2565b905060000361368b576000818152600660205260409020613689898b836158f9565b505b6040805160808101825282815263ffffffff861660208201529081016136c7896136b88a62015180615501565b6136c29190615518565b6140d8565b6001600160e01b03908116825260209182018590526000888152600483526040908190208451815592840151908401519091166401000000000263ffffffff9091161760018201556060909101516002909101558261386f5760008b81526005602052604090205485146137745760405185908c907fe08aff0930a0c84c077d2ce7e690a3f910c0f8705376b2405816efb89b9869b790600090a360008b81526005602052604090208590555b6003546040517fd23bab140000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063d23bab14906137c1908e908d908d906004016159b9565b600060405180830381600087803b1580156137db57600080fd5b505af11580156137ef573d6000803e3d6000fd5b50506003546040517fbe3cc74d000000000000000000000000000000000000000000000000000000008152600481018f90526001600160a01b03909116925063be3cc74d9150602401600060405180830381600087803b15801561385257600080fd5b505af1158015613866573d6000803e3d6000fd5b505050506138b9565b60008381526004602081815260408084206002018990558e8452600582528084205480855292909152909120600101544263ffffffff909116116138b7576138b78c82612f92565b505b6138c28a613dac565b897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663472c22f18d60405160200161390591815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161393991815260200190565b602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190614d44565b14613a01576040516391eed08560e01b8152600481018c9052602481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391eed08590604401600060405180830381600087803b1580156139e857600080fd5b505af11580156139fc573d6000803e3d6000fd5b505050505b505050509695505050505050565b600080600080878787604051613a26929190615169565b604051908190038120613a459291602001918252602082015260400190565b604051602081830303815290604052805190602001209350613a718542613a6c919061528f565b61324c565b925060008080613a83898b018b6159d3565b60008e81526005602052604081205493965091945092509081905b8015613c005760008181526004602052604081208054909350613ac69088908890889061410c565b60018085015491925063ffffffff90911690826002811115613aea57613aea615a0b565b1480613b0157508063ffffffff168b63ffffffff16115b613b4d5760405162461bcd60e51b815260206004820152601d60248201527f537562736372697074696f6e20646f6573206e6f7420757067726164650000006044820152606401610ab3565b6002826002811115613b6157613b61615a0b565b148015613b735750428163ffffffff16115b15613b8a578299508480613b8690615556565b9550505b6001826002811115613b9e57613b9e615a0b565b148015613bb657508063ffffffff168b63ffffffff16105b15613bf3578298505b8215613bec5784613bcf81615556565b60009485526004602052604090942060020154939550613bbf9050565b5050613c00565b5050506002810154613a9e565b507f00000000000000000000000000000000000000000000000000000000000000008210613c705760405162461bcd60e51b815260206004820152601760248201527f537562736372697074696f6e2071756575652066756c6c0000000000000000006044820152606401610ab3565b5050505050945094509450949050565b84613ccd5760405162461bcd60e51b815260206004820152600e60248201527f64415049206e616d65207a65726f0000000000000000000000000000000000006044820152606401610ab3565b600080613cdc838501856157bc565b915091508160016000604051602001613d18907f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000008152601b0190565b6040516020818303038152906040528051906020012081526020019081526020016000206000015414613d7c5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b60408051602081018990529081018790526001600160a01b038616606082015261320790829084906080016131cf565b6040516367a7cfb760e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906367a7cfb7906024016040805180830381865afa158015613e13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3791906155b3565b9150613e4e90506201518063ffffffff831661528f565b421115613e9d5760405162461bcd60e51b815260206004820152601560248201527f4461746120666565642076616c7565207374616c6500000000000000000000006044820152606401610ab3565b6003546040517f7a821819000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637a82181990602401602060405180830381865afa158015613eff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f239190615a21565b610b2f5760405162461bcd60e51b815260206004820152601860248201527f446174612066656564206e6f74207265676973746572656400000000000000006044820152606401610ab3565b600082613f7c85846142c9565b1490505b9392505050565b60008060008351604103613fc15760208401516040850151606086015160001a613fb38882858561430c565b955095509550505050613fcd565b50508151600091506002905b9250925092565b6000826003811115613fe857613fe8615a0b565b03613ff1575050565b600182600381111561400557614005615a0b565b0361403c576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561405057614050615a0b565b0361408a576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610ab3565b600382600381111561409e5761409e615a0b565b03610b2f576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610ab3565b60006001600160e01b0382111561327d576040516306dfcc6560e41b815260e0600482015260248101839052604401610ab3565b600081815260066020526040812080548291829182919061412c906152a2565b80601f0160208091040260200160405190810160405280929190818152602001828054614158906152a2565b80156141a55780601f1061417a576101008083540402835291602001916141a5565b820191906000526020600020905b81548152906001019060200180831161418857829003601f168201915b50505050508060200190518101906141bd9190615a3c565b92509250925081601b0b87601b0b146142185760405162461bcd60e51b815260206004820152601e60248201527f446576696174696f6e207265666572656e636573206e6f7420657175616c00006044820152606401610ab3565b828814801561422657508086145b1561423757600093505050506142c1565b8288111580156142475750808611155b1561425857600193505050506142c1565b8288101580156142685750808610155b1561427957600293505050506142c1565b60405162461bcd60e51b815260206004820152601e60248201527f55706461746520706172616d657465727320696e636f6d70617261626c6500006044820152606401610ab3565b949350505050565b600081815b8451811015614304576142fa828683815181106142ed576142ed614d7a565b60200260200101516143db565b91506001016142ce565b509392505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561434757506000915060039050826143d1565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561439b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166143c7575060009250600191508290506143d1565b9250600091508190505b9450945094915050565b60008183106143f7576000828152602084905260409020610a52565b6000838152602083905260409020610a52565b60008083601f84011261441c57600080fd5b50813567ffffffffffffffff81111561443457600080fd5b6020830191508360208260051b850101111561444f57600080fd5b9250929050565b6000806020838503121561446957600080fd5b823567ffffffffffffffff81111561448057600080fd5b61448c8582860161440a565b90969095509350505050565b6000602082840312156144aa57600080fd5b5035919050565b6001600160a01b03811681146144c657600080fd5b50565b6000602082840312156144db57600080fd5b8135613f80816144b1565b6000806000604084860312156144fb57600080fd5b83359250602084013567ffffffffffffffff81111561451957600080fd5b6145258682870161440a565b9497909650939450505050565b60008083601f84011261454457600080fd5b50813567ffffffffffffffff81111561455c57600080fd5b60208301915083602082850101111561444f57600080fd5b600080600080600080600060a0888a03121561458f57600080fd5b873561459a816144b1565b96506020880135955060408801359450606088013567ffffffffffffffff8111156145c457600080fd5b6145d08a828b01614532565b909550935050608088013567ffffffffffffffff8111156145f057600080fd5b6145fc8a828b01614532565b989b979a50959850939692959293505050565b803561461a816144b1565b919050565b60008060008060008060008060008060006101008c8e03121561464157600080fd5b8b3567ffffffffffffffff81111561465857600080fd5b6146648e828f0161440a565b909c509a505060208c0135985060408c0135975061468460608d0161460f565b965060808c013567ffffffffffffffff8111156146a057600080fd5b6146ac8e828f01614532565b90975095505060a08c0135935060c08c0135925060e08c013567ffffffffffffffff8111156146da57600080fd5b6146e68e828f01614532565b915080935050809150509295989b509295989b9093969950565b60005b8381101561471b578181015183820152602001614703565b50506000910152565b6000815180845261473c816020860160208601614700565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b838110156147a057601f1985840301885261478a838351614724565b602098890198909350919091019060010161476e565b50909695505050505050565b6040815260006147bf6040830185614750565b90508260208301529392505050565b6000806000806000606086880312156147e657600080fd5b85356147f1816144b1565b9450602086013567ffffffffffffffff81111561480d57600080fd5b61481988828901614532565b909550935050604086013567ffffffffffffffff81111561483957600080fd5b61484588828901614532565b969995985093965092949392505050565b600081518084526020840193506020830160005b8281101561488a578151151586526020958601959091019060010161486a565b5093949350505050565b6040815260006148a76040830185614856565b82810360208401526123de8185614750565b600080602083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b61448c85828601614532565b602081526000610a526020830184614724565b60008060008060006080868803121561491a57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561494657600080fd5b6148458882890161440a565b6060815260006149656060830186614856565b82810360208401526149778186614750565b915050826040830152949350505050565b602081526000610a526020830184614750565b600080600080600080600080600060e08a8c0312156149b957600080fd5b8935985060208a0135975060408a01356149d2816144b1565b965060608a013567ffffffffffffffff8111156149ee57600080fd5b6149fa8c828d01614532565b90975095505060808a0135935060a08a0135925060c08a013567ffffffffffffffff811115614a2857600080fd5b614a348c828d01614532565b915080935050809150509295985092959850929598565b600080600080600060808688031215614a6357600080fd5b85359450602086013567ffffffffffffffff811115614a8157600080fd5b614a8d88828901614532565b9699909850959660408101359660609091013595509350505050565b60008060008060608587031215614abf57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115614ae457600080fd5b614af087828801614532565b95989497509550505050565b600081518084526020840193506020830160005b8281101561488a578151601b0b865260209586019590910190600101614b10565b600081518084526020840193506020830160005b8281101561488a57815163ffffffff16865260209586019590910190600101614b45565b61010081526000614b7e61010083018b614724565b89601b0b602084015263ffffffff891660408401528281036060840152614ba58189614afc565b90508281036080840152614bb98188614b31565b905082810360a0840152614bcd8187614750565b905082810360c0840152614be18186614b31565b83810360e08501528451808252602080870193509091019060005b81811015614c235783516001600160e01b0316835260209384019390920191600101614bfc565b50909c9b505050505050505050505050565b60008060408385031215614c4857600080fd5b50508035926020909101359150565b60a081526000614c6a60a0830188614724565b86601b0b602084015263ffffffff861660408401528281036060840152614c918186614afc565b905082810360808401526110368185614b31565b600080600080600060808688031215614cbd57600080fd5b85359450602086013593506040860135614cd6816144b1565b9250606086013567ffffffffffffffff81111561483957600080fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614d2b57600080fd5b8260051b80856040850137919091016040019392505050565b600060208284031215614d5657600080fd5b5051919050565b600060208284031215614d6f57600080fd5b8151613f80816144b1565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610a5557610a55614d90565b60008184825b85811015614df0578135614dd2816144b1565b6001600160a01b031683526020928301929190910190600101614dbf565b509095945050505050565b6020808252810182905260008360408301825b85811015614e3e578235614e21816144b1565b6001600160a01b0316825260209283019290910190600101614e0e565b5095945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038816815286602082015285604082015260a060608201526000614ea060a083018688614e48565b8281036080840152614eb3818587614e48565b9a9950505050505050505050565b6020808252810182905260006040600584901b830181019083018583601e1936839003015b87821015614f5757868503603f190184528235818112614f0557600080fd5b890160208101903567ffffffffffffffff811115614f2257600080fd5b803603821315614f3157600080fd5b614f3c878284614e48565b96505050602083019250602084019350600182019150614ee6565b5092979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614fa357614fa3614f64565b604052919050565b600067ffffffffffffffff821115614fc557614fc5614f64565b5060051b60200190565b600067ffffffffffffffff821115614fe957614fe9614f64565b50601f01601f191660200190565b600061500a61500584614fcf565b614f7a565b905082815283838301111561501e57600080fd5b613f80836020830184614700565b600082601f83011261503d57600080fd5b610a5283835160208501614ff7565b600082601f83011261505d57600080fd5b815161506b61500582614fab565b8082825260208201915060208360051b86010192508583111561508d57600080fd5b602085015b83811015614e3e57805167ffffffffffffffff8111156150b157600080fd5b6150c0886020838a010161502c565b84525060209283019201615092565b6000602082840312156150e157600080fd5b815167ffffffffffffffff8111156150f857600080fd5b6142c18482850161504c565b60006020828403121561511657600080fd5b815167ffffffffffffffff81111561512d57600080fd5b8201601f8101841361513e57600080fd5b6142c184825160208401614ff7565b6000825161515f818460208701614700565b9190910192915050565b8183823760009101908152919050565b6001600160a01b03841681526040602082015260006123de604083018486614e48565b6000808335601e198436030181126151b357600080fd5b83018035915067ffffffffffffffff8211156151ce57600080fd5b60200191503681900382131561444f57600080fd5b6020815260006142c1602083018486614e48565b63ffffffff8281168282160390811115610a5557610a55614d90565b60006001600160e01b0382166001600160e01b0384166001600160e01b038183021692508183048114821517611f4b57611f4b614d90565b634e487b7160e01b600052601260045260246000fd5b60006001600160e01b0383168061527a5761527a61524b565b806001600160e01b0384160491505092915050565b80820180821115610a5557610a55614d90565b600181811c908216806152b657607f821691505b6020821081036152d657634e487b7160e01b600052602260045260246000fd5b50919050565b600082601f8301126152ed57600080fd5b81356152fb61500582614fcf565b81815284602083860101111561531057600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561534257600080fd5b83359250602084013567ffffffffffffffff81111561536057600080fd5b61536c868287016152dc565b925050604084013567ffffffffffffffff81111561538957600080fd5b615395868287016152dc565b9150509250925092565b8151600090829060208501835b828110156153d35781516001600160a01b03168452602093840193909101906001016153ac565b509195945050505050565b8051801515811461461a57600080fd5b6000806040838503121561540157600080fd5b825167ffffffffffffffff81111561541857600080fd5b8301601f8101851361542957600080fd5b805161543761500582614fab565b8082825260208201915060208360051b85010192508783111561545957600080fd5b6020840193505b8284101561548257615471846153de565b825260209384019390910190615460565b80955050505050602083015167ffffffffffffffff8111156154a357600080fd5b6154af8582860161504c565b9150509250929050565b8781526001600160a01b038716602082015260c0604082015260006154e260c083018789614e48565b606083019590955250608081019290925260a090910152949350505050565b8082028115828204841417610a5557610a55614d90565b6000826155275761552761524b565b500490565b84815283602082015260606040820152600061554c606083018486614e48565b9695505050505050565b60006001820161556857615568614d90565b5060010190565b60006020828403121561558157600080fd5b815167ffffffffffffffff81111561559857600080fd5b6142c18482850161502c565b80601b0b81146144c657600080fd5b600080604083850312156155c657600080fd5b82516155d1816155a4565b602084015190925063ffffffff811681146155eb57600080fd5b809150509250929050565b6000806040838503121561560957600080fd5b8251615614816144b1565b6020939093015192949293505050565b600082601f83011261563557600080fd5b815161564361500582614fab565b8082825260208201915060208360051b86010192508583111561566557600080fd5b602085015b83811015614e3e57805183526020928301920161566a565b6000806040838503121561569557600080fd5b825167ffffffffffffffff8111156156ac57600080fd5b8301601f810185136156bd57600080fd5b80516156cb61500582614fab565b8082825260208201915060208360051b8501019250878311156156ed57600080fd5b6020840193505b82841015615718578351615707816144b1565b8252602093840193909101906156f4565b80955050505050602083015167ffffffffffffffff81111561573957600080fd5b6154af85828601615624565b8281526040602082015260006142c16040830184614724565b600082601f83011261576f57600080fd5b813561577d61500582614fab565b8082825260208201915060208360051b86010192508583111561579f57600080fd5b602085015b83811015614e3e5780358352602092830192016157a4565b600080604083850312156157cf57600080fd5b82359150602083013567ffffffffffffffff8111156157ed57600080fd5b6154af8582860161575e565b6000806000806080858703121561580f57600080fd5b84359350602085013567ffffffffffffffff81111561582d57600080fd5b6158398782880161575e565b93505060408501359150606085013567ffffffffffffffff81111561585d57600080fd5b6158698782880161575e565b91505092959194509250565b86815285602082015260a06040820152600061589560a083018688614e48565b60608301949094525060800152949350505050565b601f8211156158f457806000526020600020601f840160051c810160208510156158d15750805b601f840160051c820191505b818110156158f157600081556001016158dd565b50505b505050565b67ffffffffffffffff83111561591157615911614f64565b6159258361591f83546152a2565b836158aa565b6000601f84116001811461595957600085156159415750838201355b600019600387901b1c1916600186901b1783556158f1565b600083815260209020601f19861690835b8281101561598a578685013582556020948501946001909201910161596a565b50868210156159a75760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8381526040602082015260006123de604083018486614e48565b6000806000606084860312156159e857600080fd5b8335925060208401356159fa816155a4565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b600060208284031215615a3357600080fd5b610a52826153de565b600080600060608486031215615a5157600080fd5b83516020850151909350615a64816155a4565b604094909401519295939450919291505056fea26469706673582212201b8cf3e3f921ba8d94c9d11a75500ff4b930f86d1e5ad035d17793956ee9e95064736f6c634300081b003300000000000000000000000081bc85f329cdb28936fbb239f734ae495121f9a60000000000000000000000001fe170311cb13e3bfb96dec8faadcf97bf843381000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode
0x6080604052600436106102f15760003560e01c8063715018a61161018f578063b7afd507116100e1578063d7fa10071161008a578063f2fde38b11610064578063f2fde38b1461093f578063f8b2cb4f1461095f578063fa0130671461098757600080fd5b8063d7fa1007146108d7578063d8d2f90f146108f7578063e637cf001461092857600080fd5b8063c6c04e16116100bb578063c6c04e1614610845578063d5659f3114610879578063d658d2e91461088e57600080fd5b8063b7afd507146107f2578063c1516e5414610805578063c30027601461082557600080fd5b806394259c6c11610143578063a89307b41161011d578063a89307b414610776578063aa2b44e414610798578063ac9650d8146107c557600080fd5b806394259c6c1461069957806397f679d314610722578063a5f36cb11461075657600080fd5b8063845ebe4311610174578063845ebe43146106215780638c9f4c791461064e5780638da5cb5b1461067b57600080fd5b8063715018a6146105f9578063796b89b91461060e57600080fd5b80633adb35fe116102485780634dcc19fe116101fc5780635989eaeb116101d65780635989eaeb1461057f5780635d868194146105b957806364c2359d146105d957600080fd5b80634dcc19fe1461053757806353130e261461054a5780635885c7711461056a57600080fd5b806342cbb15c1161022d57806342cbb15c146104d6578063437b9116146104e95780634dc610d41461051757600080fd5b80633adb35fe1461048d5780633db35663146104a257600080fd5b80631a0a0b3e116102aa578063288ddb6111610284578063288ddb61146104195780632d6a744e1461042e5780633408e4701461047a57600080fd5b80631a0a0b3e146103b85780631b1f24d8146103d85780631d911b6d146103f957600080fd5b8063044c9bd7116102db578063044c9bd71461034b5780630b62ebf21461037857806318d6e2d41461039857600080fd5b8062aae33f146102f65780630141ff4814610329575b600080fd5b34801561030257600080fd5b50610316610311366004614456565b6109a7565b6040519081526020015b60405180910390f35b34801561033557600080fd5b50610349610344366004614498565b610a5b565b005b34801561035757600080fd5b50610316610366366004614498565b60009081526001602052604090205490565b34801561038457600080fd5b506103496103933660046144c9565b610b33565b3480156103a457600080fd5b506103496103b33660046144e6565b610d18565b3480156103c457600080fd5b506103166103d3366004614574565b610f7f565b6103eb6103e636600461461f565b611042565b6040516103209291906147ac565b34801561040557600080fd5b506103496104143660046147ce565b6110e0565b34801561042557600080fd5b5061031661129a565b34801561043a57600080fd5b506104627f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a81565b6040516001600160a01b039091168152602001610320565b34801561048657600080fd5b5046610316565b34801561049957600080fd5b506103166112e0565b3480156104ae57600080fd5b506104627f0000000000000000000000001fe170311cb13e3bfb96dec8faadcf97bf84338181565b3480156104e257600080fd5b5043610316565b3480156104f557600080fd5b50610509610504366004614456565b611356565b604051610320929190614894565b34801561052357600080fd5b50610349610532366004614498565b6114bc565b34801561054357600080fd5b5048610316565b34801561055657600080fd5b50600354610462906001600160a01b031681565b34801561057657600080fd5b506103166115bd565b34801561058b57600080fd5b506105a961059a3660046144c9565b6001600160a01b03163b151590565b6040519015158152602001610320565b3480156105c557600080fd5b506103166105d43660046148b9565b6115ee565b3480156105e557600080fd5b506103166105f4366004614498565b61163a565b34801561060557600080fd5b506103496116f0565b34801561061a57600080fd5b5042610316565b34801561062d57600080fd5b5061031661063c366004614498565b60026020526000908152604090205481565b34801561065a57600080fd5b5061066e610669366004614498565b611738565b60405161032091906148ef565b34801561068757600080fd5b506000546001600160a01b0316610462565b3480156106a557600080fd5b506106ef6106b4366004614498565b600460205260009081526040902080546001820154600290920154909163ffffffff8116916401000000009091046001600160e01b03169084565b6040805194855263ffffffff90931660208501526001600160e01b03909116918301919091526060820152608001610320565b34801561072e57600080fd5b506103167f000000000000000000000000000000000000000000000000000000000000000a81565b34801561076257600080fd5b50610349610771366004614902565b6117e7565b61078961078436600461461f565b611d2f565b60405161032093929190614952565b3480156107a457600080fd5b506103166107b3366004614498565b60056020526000908152604090205481565b3480156107d157600080fd5b506107e56107e0366004614456565b611dd2565b6040516103209190614988565b61031661080036600461499b565b611f53565b34801561081157600080fd5b50610316610820366004614a4b565b612181565b34801561083157600080fd5b50610462610840366004614aa9565b61232d565b34801561085157600080fd5b50610865610860366004614498565b6123e7565b604051610320989796959493929190614b69565b34801561088557600080fd5b50610316612762565b34801561089a57600080fd5b506108c26108a9366004614498565b6001602081905260009182526040909120805491015482565b60408051928352602083019190915201610320565b3480156108e357600080fd5b506103496108f2366004614c35565b612793565b34801561090357600080fd5b50610917610912366004614498565b612804565b604051610320959493929190614c57565b34801561093457600080fd5b506103166201518081565b34801561094b57600080fd5b5061034961095a3660046144c9565b612ce3565b34801561096b57600080fd5b5061031661097a3660046144c9565b6001600160a01b03163190565b34801561099357600080fd5b506103496109a2366004614ca5565b612d2b565b6040517eaae33f0000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a169062aae33f90610a0f9086908690600401614cf2565b6020604051808303816000875af1158015610a2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a529190614d44565b90505b92915050565b60008181526005602052604090205480610abc5760405162461bcd60e51b815260206004820152601860248201527f537562736372697074696f6e20717565756520656d707479000000000000000060448201526064015b60405180910390fd5b6000818152600460205260409020600101544263ffffffff9091161115610b255760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420737562736372697074696f6e206e6f7420656e64656400006044820152606401610ab3565b610b2f8282612f92565b5050565b610b3b6130af565b6001600160a01b038116610b915760405162461bcd60e51b815260206004820152601e60248201527f4169727365656b657252656769737472792061646472657373207a65726f00006044820152606401610ab3565b6003546001600160a01b031615610bea5760405162461bcd60e51b815260206004820152601d60248201527f4169727365656b6572526567697374727920616c7265616479207365740000006044820152606401610ab3565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c569190614d5d565b6001600160a01b031614610cac5760405162461bcd60e51b815260206004820152601b60248201527f4e6f74204169727365656b65725265676973747279206f776e657200000000006044820152606401610ab3565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f90f2d5c680e476ebdec8de98d28cd387630163236f0975752747b4075c8300f89060200160405180910390a150565b610d206130af565b82610d6d5760405162461bcd60e51b815260206004820152600e60248201527f486173682074797065207a65726f0000000000000000000000000000000000006044820152606401610ab3565b806000819003610dbf5760405162461bcd60e51b815260206004820152600d60248201527f5369676e65727320656d707479000000000000000000000000000000000000006044820152606401610ab3565b600083838281610dd157610dd1614d7a565b9050602002016020810190610de691906144c9565b6001600160a01b031603610e3c5760405162461bcd60e51b815260206004820152601960248201527f4669727374207369676e65722061646472657373207a65726f000000000000006044820152606401610ab3565b60015b81811015610f06578383610e54600184614da6565b818110610e6357610e63614d7a565b9050602002016020810190610e7891906144c9565b6001600160a01b0316848483818110610e9357610e93614d7a565b9050602002016020810190610ea891906144c9565b6001600160a01b031611610efe5760405162461bcd60e51b815260206004820152601e60248201527f5369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610ab3565b600101610e3f565b508282604051602001610f1a929190614db9565b60408051601f198184030181528282528051602091820120600088815260029092529190205584907f5a1f5ee4ceedd78b1982374b4790e8aa9f31e8af1c32aaef46b2afd8a789193a90610f719086908690614dfb565b60405180910390a250505050565b6040517f1a0a0b3e0000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a1690631a0a0b3e90610ff3908b908b908b908b908b908b908b90600401614e71565b6020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110369190614d44565b98975050505050505050565b60606000306001600160a01b031663ac9650d88e8e6040518363ffffffff1660e01b8152600401611074929190614ec1565b6000604051808303816000875af1158015611093573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110bb91908101906150cf565b91506110ce8b8b8b8b8b8b8b8b8b611f53565b90509b509b9950505050505050505050565b6110ed8585858585613106565b6003546040517f085df6ab0000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301529091169063085df6ab90602401600060405180830381865afa158015611150573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111789190810190615104565b604051602001611188919061514d565b6040516020818303038152906040528051906020012084846040516020016111b1929190615169565b60405160208183030381529060405280519060200120036112145760405162461bcd60e51b815260206004820152601e60248201527f446f6573206e6f7420757064617465207369676e6564204150492055524c00006044820152606401610ab3565b6003546040517ffba8f22f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063fba8f22f9061126190889088908890600401615179565b600060405180830381600087803b15801561127b57600080fd5b505af115801561128f573d6000803e3d6000fd5b505050505050505050565b6040517f644150492070726963696e67204d65726b6c6520726f6f74000000000000000060208201526038015b6040516020818303038152906040528051906020012081565b600060405160200161133b907f417069334d61726b65745632207369676e61747572652064656c65676174696f81527f6e00000000000000000000000000000000000000000000000000000000000000602082015260210190565b60405160208183030381529060405280519060200120905090565b606080828067ffffffffffffffff81111561137357611373614f64565b60405190808252806020026020018201604052801561139c578160200160208202803683370190505b5092508067ffffffffffffffff8111156113b8576113b8614f64565b6040519080825280602002602001820160405280156113eb57816020015b60608152602001906001900390816113d65790505b50915060005b818110156114b3573086868381811061140c5761140c614d7a565b905060200281019061141e919061519c565b60405161142c929190615169565b600060405180830381855af49150503d8060008114611467576040519150601f19603f3d011682016040523d82523d6000602084013e61146c565b606091505b5085838151811061147f5761147f614d7a565b6020026020010185848151811061149857611498614d7a565b602090810291909101019190915290151590526001016113f1565b50509250929050565b6114c46130af565b60008181526005602052604090205461151f5760405162461bcd60e51b815260206004820152601860248201527f537562736372697074696f6e20717565756520656d70747900000000000000006044820152606401610ab3565b600081815260056020526040808220919091556003549051632412a9cb60e01b8152600481018390526001600160a01b0390911690632412a9cb90602401600060405180830381600087803b15801561157757600080fd5b505af115801561158b573d6000803e3d6000fd5b50506040518392507f07731f198aeecb61ff6de517fa82a003ba1bb3846140b23b62d7563dc2ddfb6a9150600090a250565b6040517f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000006020820152603b016112c7565b6003546040517f5d8681940000000000000000000000000000000000000000000000000000000081526000916001600160a01b031690635d86819490610a0f90869086906004016151e3565b6000806116464261324c565b600084815260056020526040812054919250905b80156116e8576000818152600460205260409020600181015490925063ffffffff16428111156116dc576001830154620151809064010000000090046001600160e01b03166116a986846151f7565b63ffffffff166116b99190615213565b6116c39190615261565b6116d6906001600160e01b03168661528f565b94508093505b5050600281015461165a565b505050919050565b60405162461bcd60e51b815260206004820152601d60248201527f4f776e6572736869702063616e6e6f742062652072656e6f756e6365640000006044820152606401610ab3565b600081815260046020908152604080832054835260069091529020805460609190611762906152a2565b80601f016020809104026020016040519081016040528092919081815260200182805461178e906152a2565b80156117db5780601f106117b0576101008083540402835291602001916117db565b820191906000526020600020905b8154815290600101906020018083116117be57829003601f168201915b50505050509050919050565b836118345760405162461bcd60e51b815260206004820152600f60248201527f486173682076616c7565207a65726f00000000000000000000000000000000006044820152606401610ab3565b428311156118845760405162461bcd60e51b815260206004820152601a60248201527f486173682074696d657374616d702066726f6d206675747572650000000000006044820152606401610ab3565b6000858152600160208190526040909120015483116118e55760405162461bcd60e51b815260206004820152601e60248201527f486173682074696d657374616d70206e6f74206d6f726520726563656e7400006044820152606401610ab3565b600085815260026020526040902054806119415760405162461bcd60e51b815260206004820152600f60248201527f5369676e657273206e6f742073657400000000000000000000000000000000006044820152606401610ab3565b8160008167ffffffffffffffff81111561195d5761195d614f64565b604051908082528060200260200182016040528015611986578160200160208202803683370190505b5060408051602081018b9052908101899052606081018890529091506000906119f6906080015b604051602081830303815290604052805190602001207f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060005b83811015611c41576000878783818110611a1757611a17614d7a565b9050602002810190611a29919061519c565b9150506040198101611ace57611a9783898985818110611a4b57611a4b614d7a565b9050602002810190611a5d919061519c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061328192505050565b848381518110611aa957611aa9614d7a565b60200260200101906001600160a01b031690816001600160a01b031681525050611c38565b6101608103611bf05760008060008a8a86818110611aee57611aee614d7a565b9050602002810190611b00919061519c565b810190611b0d919061532d565b925092509250824210611b625760405162461bcd60e51b815260206004820152601060248201527f44656c65676174696f6e20656e646564000000000000000000000000000000006044820152606401610ab3565b611bb6611bb0611b706112e0565b611b7a8985613281565b866040516020016119ad9392919092835260609190911b6bffffffffffffffffffffffff19166020830152603482015260540190565b83613281565b878681518110611bc857611bc8614d7a565b60200260200101906001600160a01b031690816001600160a01b031681525050505050611c38565b60405162461bcd60e51b815260206004820152601860248201527f496e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610ab3565b506001016119fb565b5081604051602001611c53919061539f565b604051602081830303815290604052805190602001208414611cb75760405162461bcd60e51b815260206004820152601260248201527f5369676e6174757265206d69736d6174636800000000000000000000000000006044820152606401610ab3565b60408051808201825289815260208082018a815260008d815260019283905284902092518355519101555189907fa33e8931ee2a869317bbe04201dab2907fd39d2d7f014c15b8459986e62c279190611d1c908b908b90918252602082015260400190565b60405180910390a2505050505050505050565b6060806000306001600160a01b031663437b91168f8f6040518363ffffffff1660e01b8152600401611d62929190614ec1565b6000604051808303816000875af1158015611d81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da991908101906153ee565b9093509150611dbf8c8c8c8c8c8c8c8c8c611f53565b90509b509b509b98505050505050505050565b6060818067ffffffffffffffff811115611dee57611dee614f64565b604051908082528060200260200182016040528015611e2157816020015b6060815260200190600190039081611e0c5790505b50915060005b81811015611f4b57600030868684818110611e4457611e44614d7a565b9050602002810190611e56919061519c565b604051611e64929190615169565b600060405180830381855af49150503d8060008114611e9f576040519150601f19603f3d011682016040523d82523d6000602084013e611ea4565b606091505b50858481518110611eb757611eb7614d7a565b6020908102919091010152905080611f42576000848381518110611edd57611edd614d7a565b60200260200101519050600081511115611efa5780518082602001fd5b60405162461bcd60e51b815260206004820152601b60248201527f4d756c746963616c6c3a204e6f2072657665727420737472696e6700000000006044820152606401610ab3565b50600101611e27565b505092915050565b600088611fa25760405162461bcd60e51b815260206004820152601160248201527f446174612066656564204944207a65726f0000000000000000000000000000006044820152606401610ab3565b6001600160a01b038816611ff85760405162461bcd60e51b815260206004820152601b60248201527f53706f6e736f722077616c6c65742061646472657373207a65726f00000000006044820152606401610ab3565b6120098a8a8a8a8a8a8a8a8a6132ab565b6120178a8a89898989613610565b90506120228a61163a565b612036346001600160a01b038b163161528f565b10156120845760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e74207061796d656e740000000000000000000000006044820152606401610ab3565b808a7fd44e8abecc305a9434d27a049c731a8331cee8bca6496154f47835b396ce55068b8b8b8b8b8b346040516120c197969594939291906154b9565b60405180910390a33415612174576000886001600160a01b03163460405160006040518083038185875af1925050503d806000811461211c576040519150601f19603f3d011682016040523d82523d6000602084013e612121565b606091505b50509050806121725760405162461bcd60e51b815260206004820152601560248201527f5472616e7366657220756e7375636365737366756c00000000000000000000006044820152606401610ab3565b505b9998505050505050505050565b6000606084146121d35760405162461bcd60e51b815260206004820181905260248201527f55706461746520706172616d6574657273206c656e67746820696e76616c69646044820152606401610ab3565b6000806000806121e58a8a8a8a613a0f565b935093509350935060008787620151806121ff9190615501565b6122099190615518565b905060006122164261324c565b9050600084156122345760008d815260056020526040902054612236565b865b90505b801561231d5786810361228657620151808361225584896151f7565b63ffffffff166122659190615501565b61226f9190615518565b612279908961528f565b9750859150839050612239565b6000818152600460205260409020600181015463ffffffff16428111156122ff576001820154620151809064010000000090046001600160e01b03166122cc86846151f7565b63ffffffff166122dc9190615213565b6122e69190615261565b6122f9906001600160e01b03168b61528f565b99508093505b82870361230e57889250612316565b816002015492505b5050612239565b5050505050505095945050505050565b6040517fc30027600000000000000000000000000000000000000000000000000000000081526000906001600160a01b037f0000000000000000000000001fe170311cb13e3bfb96dec8faadcf97bf843381169063c30027609061239b90889088908890889060040161552c565b6020604051808303816000875af11580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190614d5d565b95945050505050565b6060600080606080606080606060007f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b031663472c22f18b60405160200161243891815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161246c91815260200190565b602060405180830381865afa158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190614d44565b90506124b881612804565b60008f815260056020526040812054959e50939c50919a5098509650905b801561250357816124e681615556565b600092835260046020526040909220600201549192506124d69050565b508067ffffffffffffffff81111561251d5761251d614f64565b60405190808252806020026020018201604052801561255057816020015b606081526020019060019003908161253b5790505b5094508067ffffffffffffffff81111561256c5761256c614f64565b604051908082528060200260200182016040528015612595578160200160208202803683370190505b5093508067ffffffffffffffff8111156125b1576125b1614f64565b6040519080825280602002602001820160405280156125da578160200160208202803683370190505b5060008c8152600560209081526040808320548352600490915281209194505b828110156127535781546000908152600660205260409020805461261d906152a2565b80601f0160208091040260200160405190810160405280929190818152602001828054612649906152a2565b80156126965780601f1061266b57610100808354040283529160200191612696565b820191906000526020600020905b81548152906001019060200180831161267957829003601f168201915b50505050508782815181106126ad576126ad614d7a565b60209081029190910101526001820154865163ffffffff909116908790839081106126da576126da614d7a565b602002602001019063ffffffff16908163ffffffff16815250508160010160049054906101000a90046001600160e01b031685828151811061271e5761271e614d7a565b6001600160e01b03909216602092830291909101820152600290920154600090815260049092526040909120906001016125fa565b50505050919395975091939597565b6040517f5369676e6564204150492055524c204d65726b6c6520726f6f740000000000006020820152603a016112c7565b61279b6130af565b604080518082018252828152426020808301828152600087815260018084529086902094518555905193019290925582518481529182015283917f19cb5bc6996c2541fb44252778e9c8c952662cce4670a75a4174b50c765bd7d1910160405180910390a25050565b6003546040517f6e85b69a000000000000000000000000000000000000000000000000000000008152600481018390526060916000918291849182916001600160a01b031690636e85b69a90602401600060405180830381865afa158015612870573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612898919081019061556f565b6040516367a7cfb760e01b8152600481018890529095507f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b0316906367a7cfb7906024016040805180830381865afa1580156128ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292391906155b3565b86519195509350603f1901612abd57604080516001808252818301909252906020808301908036833750506040805160018082528183019092529294509050602080830190803683370190505090506000808680602001905181019061298991906155f6565b915091507f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b03166367a7cfb7612a0884846040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6040518263ffffffff1660e01b8152600401612a2691815260200190565b6040805180830381865afa158015612a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6691906155b3565b85600081518110612a7957612a79614d7a565b6020026020010185600081518110612a9357612a93614d7a565b602002602001018263ffffffff1663ffffffff1681525082601b0b601b0b81525050505050612cda565b845115612cda5760008086806020019051810190612adb9190615682565b815191935091508067ffffffffffffffff811115612afb57612afb614f64565b604051908082528060200260200182016040528015612b24578160200160208202803683370190505b5094508067ffffffffffffffff811115612b4057612b40614f64565b604051908082528060200260200182016040528015612b69578160200160208202803683370190505b50935060005b81811015612cd5577f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b03166367a7cfb7612c24868481518110612bbb57612bbb614d7a565b6020026020010151868581518110612bd557612bd5614d7a565b60200260200101516040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b6040518263ffffffff1660e01b8152600401612c4291815260200190565b6040805180830381865afa158015612c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8291906155b3565b878381518110612c9457612c94614d7a565b60200260200101878481518110612cad57612cad614d7a565b63ffffffff90931660209384029190910190920191909152601b9190910b9052600101612b6f565b505050505b91939590929450565b60405162461bcd60e51b815260206004820152601f60248201527f4f776e6572736869702063616e6e6f74206265207472616e73666572726564006044820152606401610ab3565b8315612d8c576001600160a01b038316612d875760405162461bcd60e51b815260206004820152601b60248201527f53706f6e736f722077616c6c65742061646472657373207a65726f00000000006044820152606401610ab3565b612de3565b6001600160a01b03831615612de35760405162461bcd60e51b815260206004820152601f60248201527f53706f6e736f722077616c6c65742061646472657373206e6f74207a65726f006044820152606401610ab3565b612df08585858585613c80565b60007f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b031663472c22f187604051602001612e3491815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401612e6891815260200190565b602060405180830381865afa158015612e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea99190614d44565b9050848103612efa5760405162461bcd60e51b815260206004820152601960248201527f446f6573206e6f74207570646174652064415049206e616d65000000000000006044820152606401610ab3565b8415612f0957612f0985613dac565b6040516391eed08560e01b815260048101879052602481018690527f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b0316906391eed08590604401600060405180830381600087803b158015612f7257600080fd5b505af1158015612f86573d6000803e3d6000fd5b50505050505050505050565b5b6000908152600460205260409020600201548015801590612fcd57506000818152600460205260409020600101544263ffffffff90911611155b612f9357604051819083907fe08aff0930a0c84c077d2ce7e690a3f910c0f8705376b2405816efb89b9869b790600090a360008281526005602052604090208190558061307757600354604051632412a9cb60e01b8152600481018490526001600160a01b0390911690632412a9cb906024015b600060405180830381600087803b15801561305b57600080fd5b505af115801561306f573d6000803e3d6000fd5b505050505050565b6003546001600160a01b031663d23bab148361309284611738565b6040518363ffffffff1660e01b8152600401613041929190615745565b336130c26000546001600160a01b031690565b6001600160a01b031614613104576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ab3565b565b600080613115838501856157bc565b915091508160016000604051602001613151907f5369676e6564204150492055524c204d65726b6c6520726f6f740000000000008152601a0190565b60405160208183030381529060405280519060200120815260200190815260200160002060000154146131b55760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b61320781838989896040516020016131cf93929190615179565b60408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120613f6f565b6132435760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b50505050505050565b600063ffffffff82111561327d576040516306dfcc6560e41b81526020600482015260248101839052604401610ab3565b5090565b6000806000806132918686613f87565b9250925092506132a18282613fd4565b5090949350505050565b886132f85760405162461bcd60e51b815260206004820152600e60248201527f64415049206e616d65207a65726f0000000000000000000000000000000000006044820152606401610ab3565b606085146133485760405162461bcd60e51b815260206004820181905260248201527f55706461746520706172616d6574657273206c656e67746820696e76616c69646044820152606401610ab3565b836000036133985760405162461bcd60e51b815260206004820152600d60248201527f4475726174696f6e207a65726f000000000000000000000000000000000000006044820152606401610ab3565b826000036133e85760405162461bcd60e51b815260206004820152600a60248201527f5072696365207a65726f000000000000000000000000000000000000000000006044820152606401610ab3565b60008080806133f9858701876157f9565b93509350935093508360016000604051602001613439907f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000008152601b0190565b604051602081830303815290604052805190602001208152602001908152602001600020600001541461349d5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b60408051602081018f90529081018d90526001600160a01b038c1660608201526134cd90849086906080016131cf565b6135095760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b8160016000604051602001613541907f644150492070726963696e67204d65726b6c6520726f6f740000000000000000815260180190565b60405160208183030381529060405280519060200120815260200190815260200160002060000154146135a55760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b6135c581838f468e8e8e8e6040516020016131cf96959493929190615875565b6136015760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610ab3565b50505050505050505050505050565b6000806000806136228a898989613a0f565b6040519397509195509350915060009061363f908a908a90615169565b60405180910390209050600660008281526020019081526020016000208054613667906152a2565b905060000361368b576000818152600660205260409020613689898b836158f9565b505b6040805160808101825282815263ffffffff861660208201529081016136c7896136b88a62015180615501565b6136c29190615518565b6140d8565b6001600160e01b03908116825260209182018590526000888152600483526040908190208451815592840151908401519091166401000000000263ffffffff9091161760018201556060909101516002909101558261386f5760008b81526005602052604090205485146137745760405185908c907fe08aff0930a0c84c077d2ce7e690a3f910c0f8705376b2405816efb89b9869b790600090a360008b81526005602052604090208590555b6003546040517fd23bab140000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063d23bab14906137c1908e908d908d906004016159b9565b600060405180830381600087803b1580156137db57600080fd5b505af11580156137ef573d6000803e3d6000fd5b50506003546040517fbe3cc74d000000000000000000000000000000000000000000000000000000008152600481018f90526001600160a01b03909116925063be3cc74d9150602401600060405180830381600087803b15801561385257600080fd5b505af1158015613866573d6000803e3d6000fd5b505050506138b9565b60008381526004602081815260408084206002018990558e8452600582528084205480855292909152909120600101544263ffffffff909116116138b7576138b78c82612f92565b505b6138c28a613dac565b897f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b031663472c22f18d60405160200161390591815260200190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161393991815260200190565b602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190614d44565b14613a01576040516391eed08560e01b8152600481018c9052602481018b90527f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b0316906391eed08590604401600060405180830381600087803b1580156139e857600080fd5b505af11580156139fc573d6000803e3d6000fd5b505050505b505050509695505050505050565b600080600080878787604051613a26929190615169565b604051908190038120613a459291602001918252602082015260400190565b604051602081830303815290604052805190602001209350613a718542613a6c919061528f565b61324c565b925060008080613a83898b018b6159d3565b60008e81526005602052604081205493965091945092509081905b8015613c005760008181526004602052604081208054909350613ac69088908890889061410c565b60018085015491925063ffffffff90911690826002811115613aea57613aea615a0b565b1480613b0157508063ffffffff168b63ffffffff16115b613b4d5760405162461bcd60e51b815260206004820152601d60248201527f537562736372697074696f6e20646f6573206e6f7420757067726164650000006044820152606401610ab3565b6002826002811115613b6157613b61615a0b565b148015613b735750428163ffffffff16115b15613b8a578299508480613b8690615556565b9550505b6001826002811115613b9e57613b9e615a0b565b148015613bb657508063ffffffff168b63ffffffff16105b15613bf3578298505b8215613bec5784613bcf81615556565b60009485526004602052604090942060020154939550613bbf9050565b5050613c00565b5050506002810154613a9e565b507f000000000000000000000000000000000000000000000000000000000000000a8210613c705760405162461bcd60e51b815260206004820152601760248201527f537562736372697074696f6e2071756575652066756c6c0000000000000000006044820152606401610ab3565b5050505050945094509450949050565b84613ccd5760405162461bcd60e51b815260206004820152600e60248201527f64415049206e616d65207a65726f0000000000000000000000000000000000006044820152606401610ab3565b600080613cdc838501856157bc565b915091508160016000604051602001613d18907f64415049206d616e6167656d656e74204d65726b6c6520726f6f7400000000008152601b0190565b6040516020818303038152906040528051906020012081526020019081526020016000206000015414613d7c5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610ab3565b60408051602081018990529081018790526001600160a01b038616606082015261320790829084906080016131cf565b6040516367a7cfb760e01b8152600481018290526000907f000000000000000000000000709944a48caf83535e43471680fda4905fb3920a6001600160a01b0316906367a7cfb7906024016040805180830381865afa158015613e13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3791906155b3565b9150613e4e90506201518063ffffffff831661528f565b421115613e9d5760405162461bcd60e51b815260206004820152601560248201527f4461746120666565642076616c7565207374616c6500000000000000000000006044820152606401610ab3565b6003546040517f7a821819000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637a82181990602401602060405180830381865afa158015613eff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f239190615a21565b610b2f5760405162461bcd60e51b815260206004820152601860248201527f446174612066656564206e6f74207265676973746572656400000000000000006044820152606401610ab3565b600082613f7c85846142c9565b1490505b9392505050565b60008060008351604103613fc15760208401516040850151606086015160001a613fb38882858561430c565b955095509550505050613fcd565b50508151600091506002905b9250925092565b6000826003811115613fe857613fe8615a0b565b03613ff1575050565b600182600381111561400557614005615a0b565b0361403c576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561405057614050615a0b565b0361408a576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610ab3565b600382600381111561409e5761409e615a0b565b03610b2f576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610ab3565b60006001600160e01b0382111561327d576040516306dfcc6560e41b815260e0600482015260248101839052604401610ab3565b600081815260066020526040812080548291829182919061412c906152a2565b80601f0160208091040260200160405190810160405280929190818152602001828054614158906152a2565b80156141a55780601f1061417a576101008083540402835291602001916141a5565b820191906000526020600020905b81548152906001019060200180831161418857829003601f168201915b50505050508060200190518101906141bd9190615a3c565b92509250925081601b0b87601b0b146142185760405162461bcd60e51b815260206004820152601e60248201527f446576696174696f6e207265666572656e636573206e6f7420657175616c00006044820152606401610ab3565b828814801561422657508086145b1561423757600093505050506142c1565b8288111580156142475750808611155b1561425857600193505050506142c1565b8288101580156142685750808610155b1561427957600293505050506142c1565b60405162461bcd60e51b815260206004820152601e60248201527f55706461746520706172616d657465727320696e636f6d70617261626c6500006044820152606401610ab3565b949350505050565b600081815b8451811015614304576142fa828683815181106142ed576142ed614d7a565b60200260200101516143db565b91506001016142ce565b509392505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561434757506000915060039050826143d1565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561439b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166143c7575060009250600191508290506143d1565b9250600091508190505b9450945094915050565b60008183106143f7576000828152602084905260409020610a52565b6000838152602083905260409020610a52565b60008083601f84011261441c57600080fd5b50813567ffffffffffffffff81111561443457600080fd5b6020830191508360208260051b850101111561444f57600080fd5b9250929050565b6000806020838503121561446957600080fd5b823567ffffffffffffffff81111561448057600080fd5b61448c8582860161440a565b90969095509350505050565b6000602082840312156144aa57600080fd5b5035919050565b6001600160a01b03811681146144c657600080fd5b50565b6000602082840312156144db57600080fd5b8135613f80816144b1565b6000806000604084860312156144fb57600080fd5b83359250602084013567ffffffffffffffff81111561451957600080fd5b6145258682870161440a565b9497909650939450505050565b60008083601f84011261454457600080fd5b50813567ffffffffffffffff81111561455c57600080fd5b60208301915083602082850101111561444f57600080fd5b600080600080600080600060a0888a03121561458f57600080fd5b873561459a816144b1565b96506020880135955060408801359450606088013567ffffffffffffffff8111156145c457600080fd5b6145d08a828b01614532565b909550935050608088013567ffffffffffffffff8111156145f057600080fd5b6145fc8a828b01614532565b989b979a50959850939692959293505050565b803561461a816144b1565b919050565b60008060008060008060008060008060006101008c8e03121561464157600080fd5b8b3567ffffffffffffffff81111561465857600080fd5b6146648e828f0161440a565b909c509a505060208c0135985060408c0135975061468460608d0161460f565b965060808c013567ffffffffffffffff8111156146a057600080fd5b6146ac8e828f01614532565b90975095505060a08c0135935060c08c0135925060e08c013567ffffffffffffffff8111156146da57600080fd5b6146e68e828f01614532565b915080935050809150509295989b509295989b9093969950565b60005b8381101561471b578181015183820152602001614703565b50506000910152565b6000815180845261473c816020860160208601614700565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b838110156147a057601f1985840301885261478a838351614724565b602098890198909350919091019060010161476e565b50909695505050505050565b6040815260006147bf6040830185614750565b90508260208301529392505050565b6000806000806000606086880312156147e657600080fd5b85356147f1816144b1565b9450602086013567ffffffffffffffff81111561480d57600080fd5b61481988828901614532565b909550935050604086013567ffffffffffffffff81111561483957600080fd5b61484588828901614532565b969995985093965092949392505050565b600081518084526020840193506020830160005b8281101561488a578151151586526020958601959091019060010161486a565b5093949350505050565b6040815260006148a76040830185614856565b82810360208401526123de8185614750565b600080602083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b61448c85828601614532565b602081526000610a526020830184614724565b60008060008060006080868803121561491a57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561494657600080fd5b6148458882890161440a565b6060815260006149656060830186614856565b82810360208401526149778186614750565b915050826040830152949350505050565b602081526000610a526020830184614750565b600080600080600080600080600060e08a8c0312156149b957600080fd5b8935985060208a0135975060408a01356149d2816144b1565b965060608a013567ffffffffffffffff8111156149ee57600080fd5b6149fa8c828d01614532565b90975095505060808a0135935060a08a0135925060c08a013567ffffffffffffffff811115614a2857600080fd5b614a348c828d01614532565b915080935050809150509295985092959850929598565b600080600080600060808688031215614a6357600080fd5b85359450602086013567ffffffffffffffff811115614a8157600080fd5b614a8d88828901614532565b9699909850959660408101359660609091013595509350505050565b60008060008060608587031215614abf57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115614ae457600080fd5b614af087828801614532565b95989497509550505050565b600081518084526020840193506020830160005b8281101561488a578151601b0b865260209586019590910190600101614b10565b600081518084526020840193506020830160005b8281101561488a57815163ffffffff16865260209586019590910190600101614b45565b61010081526000614b7e61010083018b614724565b89601b0b602084015263ffffffff891660408401528281036060840152614ba58189614afc565b90508281036080840152614bb98188614b31565b905082810360a0840152614bcd8187614750565b905082810360c0840152614be18186614b31565b83810360e08501528451808252602080870193509091019060005b81811015614c235783516001600160e01b0316835260209384019390920191600101614bfc565b50909c9b505050505050505050505050565b60008060408385031215614c4857600080fd5b50508035926020909101359150565b60a081526000614c6a60a0830188614724565b86601b0b602084015263ffffffff861660408401528281036060840152614c918186614afc565b905082810360808401526110368185614b31565b600080600080600060808688031215614cbd57600080fd5b85359450602086013593506040860135614cd6816144b1565b9250606086013567ffffffffffffffff81111561483957600080fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614d2b57600080fd5b8260051b80856040850137919091016040019392505050565b600060208284031215614d5657600080fd5b5051919050565b600060208284031215614d6f57600080fd5b8151613f80816144b1565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610a5557610a55614d90565b60008184825b85811015614df0578135614dd2816144b1565b6001600160a01b031683526020928301929190910190600101614dbf565b509095945050505050565b6020808252810182905260008360408301825b85811015614e3e578235614e21816144b1565b6001600160a01b0316825260209283019290910190600101614e0e565b5095945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038816815286602082015285604082015260a060608201526000614ea060a083018688614e48565b8281036080840152614eb3818587614e48565b9a9950505050505050505050565b6020808252810182905260006040600584901b830181019083018583601e1936839003015b87821015614f5757868503603f190184528235818112614f0557600080fd5b890160208101903567ffffffffffffffff811115614f2257600080fd5b803603821315614f3157600080fd5b614f3c878284614e48565b96505050602083019250602084019350600182019150614ee6565b5092979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614fa357614fa3614f64565b604052919050565b600067ffffffffffffffff821115614fc557614fc5614f64565b5060051b60200190565b600067ffffffffffffffff821115614fe957614fe9614f64565b50601f01601f191660200190565b600061500a61500584614fcf565b614f7a565b905082815283838301111561501e57600080fd5b613f80836020830184614700565b600082601f83011261503d57600080fd5b610a5283835160208501614ff7565b600082601f83011261505d57600080fd5b815161506b61500582614fab565b8082825260208201915060208360051b86010192508583111561508d57600080fd5b602085015b83811015614e3e57805167ffffffffffffffff8111156150b157600080fd5b6150c0886020838a010161502c565b84525060209283019201615092565b6000602082840312156150e157600080fd5b815167ffffffffffffffff8111156150f857600080fd5b6142c18482850161504c565b60006020828403121561511657600080fd5b815167ffffffffffffffff81111561512d57600080fd5b8201601f8101841361513e57600080fd5b6142c184825160208401614ff7565b6000825161515f818460208701614700565b9190910192915050565b8183823760009101908152919050565b6001600160a01b03841681526040602082015260006123de604083018486614e48565b6000808335601e198436030181126151b357600080fd5b83018035915067ffffffffffffffff8211156151ce57600080fd5b60200191503681900382131561444f57600080fd5b6020815260006142c1602083018486614e48565b63ffffffff8281168282160390811115610a5557610a55614d90565b60006001600160e01b0382166001600160e01b0384166001600160e01b038183021692508183048114821517611f4b57611f4b614d90565b634e487b7160e01b600052601260045260246000fd5b60006001600160e01b0383168061527a5761527a61524b565b806001600160e01b0384160491505092915050565b80820180821115610a5557610a55614d90565b600181811c908216806152b657607f821691505b6020821081036152d657634e487b7160e01b600052602260045260246000fd5b50919050565b600082601f8301126152ed57600080fd5b81356152fb61500582614fcf565b81815284602083860101111561531057600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561534257600080fd5b83359250602084013567ffffffffffffffff81111561536057600080fd5b61536c868287016152dc565b925050604084013567ffffffffffffffff81111561538957600080fd5b615395868287016152dc565b9150509250925092565b8151600090829060208501835b828110156153d35781516001600160a01b03168452602093840193909101906001016153ac565b509195945050505050565b8051801515811461461a57600080fd5b6000806040838503121561540157600080fd5b825167ffffffffffffffff81111561541857600080fd5b8301601f8101851361542957600080fd5b805161543761500582614fab565b8082825260208201915060208360051b85010192508783111561545957600080fd5b6020840193505b8284101561548257615471846153de565b825260209384019390910190615460565b80955050505050602083015167ffffffffffffffff8111156154a357600080fd5b6154af8582860161504c565b9150509250929050565b8781526001600160a01b038716602082015260c0604082015260006154e260c083018789614e48565b606083019590955250608081019290925260a090910152949350505050565b8082028115828204841417610a5557610a55614d90565b6000826155275761552761524b565b500490565b84815283602082015260606040820152600061554c606083018486614e48565b9695505050505050565b60006001820161556857615568614d90565b5060010190565b60006020828403121561558157600080fd5b815167ffffffffffffffff81111561559857600080fd5b6142c18482850161502c565b80601b0b81146144c657600080fd5b600080604083850312156155c657600080fd5b82516155d1816155a4565b602084015190925063ffffffff811681146155eb57600080fd5b809150509250929050565b6000806040838503121561560957600080fd5b8251615614816144b1565b6020939093015192949293505050565b600082601f83011261563557600080fd5b815161564361500582614fab565b8082825260208201915060208360051b86010192508583111561566557600080fd5b602085015b83811015614e3e57805183526020928301920161566a565b6000806040838503121561569557600080fd5b825167ffffffffffffffff8111156156ac57600080fd5b8301601f810185136156bd57600080fd5b80516156cb61500582614fab565b8082825260208201915060208360051b8501019250878311156156ed57600080fd5b6020840193505b82841015615718578351615707816144b1565b8252602093840193909101906156f4565b80955050505050602083015167ffffffffffffffff81111561573957600080fd5b6154af85828601615624565b8281526040602082015260006142c16040830184614724565b600082601f83011261576f57600080fd5b813561577d61500582614fab565b8082825260208201915060208360051b86010192508583111561579f57600080fd5b602085015b83811015614e3e5780358352602092830192016157a4565b600080604083850312156157cf57600080fd5b82359150602083013567ffffffffffffffff8111156157ed57600080fd5b6154af8582860161575e565b6000806000806080858703121561580f57600080fd5b84359350602085013567ffffffffffffffff81111561582d57600080fd5b6158398782880161575e565b93505060408501359150606085013567ffffffffffffffff81111561585d57600080fd5b6158698782880161575e565b91505092959194509250565b86815285602082015260a06040820152600061589560a083018688614e48565b60608301949094525060800152949350505050565b601f8211156158f457806000526020600020601f840160051c810160208510156158d15750805b601f840160051c820191505b818110156158f157600081556001016158dd565b50505b505050565b67ffffffffffffffff83111561591157615911614f64565b6159258361591f83546152a2565b836158aa565b6000601f84116001811461595957600085156159415750838201355b600019600387901b1c1916600186901b1783556158f1565b600083815260209020601f19861690835b8281101561598a578685013582556020948501946001909201910161596a565b50868210156159a75760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8381526040602082015260006123de604083018486614e48565b6000806000606084860312156159e857600080fd5b8335925060208401356159fa816155a4565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b600060208284031215615a3357600080fd5b610a52826153de565b600080600060608486031215615a5157600080fd5b83516020850151909350615a64816155a4565b604094909401519295939450919291505056fea26469706673582212201b8cf3e3f921ba8d94c9d11a75500ff4b930f86d1e5ad035d17793956ee9e95064736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000081bc85f329cdb28936fbb239f734ae495121f9a60000000000000000000000001fe170311cb13e3bfb96dec8faadcf97bf843381000000000000000000000000000000000000000000000000000000000000000a
-----Decoded View---------------
Arg [0] : owner_ (address): 0x81bc85f329cDB28936FbB239f734AE495121F9A6
Arg [1] : api3ReaderProxyV1Factory_ (address): 0x1Fe170311Cb13e3bfB96DeC8FAadcf97BF843381
Arg [2] : maximumSubscriptionQueueLength_ (uint256): 10
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000081bc85f329cdb28936fbb239f734ae495121f9a6
Arg [1] : 0000000000000000000000001fe170311cb13e3bfb96dec8faadcf97bf843381
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode Sourcemap
2332:50018:11:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22743:229;;;;;;;;;;-1:-1:-1;22743:229:11;;;;;:::i;:::-;;:::i;:::-;;;974:25:97;;;962:2;947:18;22743:229:11;;;;;;;;13465:545;;;;;;;;;;-1:-1:-1;13465:545:11;;;;;:::i;:::-;;:::i;:::-;;9261:156:2;;;;;;;;;;-1:-1:-1;9261:156:2;;;;;:::i;:::-;9347:17;9388:16;;;:6;:16;;;;;:22;;9261:156;8597:843:11;;;;;;;;;;-1:-1:-1;8597:843:11;;;;;:::i;:::-;;:::i;3863:681:2:-;;;;;;;;;;-1:-1:-1;3863:681:2;;;;;:::i;:::-;;:::i;22080:463:11:-;;;;;;;;;;-1:-1:-1;22080:463:11;;;;;:::i;:::-;;:::i;18465:758::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;16821:779::-;;;;;;;;;;-1:-1:-1;16821:779:11;;;;;:::i;:::-;;:::i;3365:133::-;;;;;;;;;;;;;:::i;4005:46::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7915:55:97;;;7897:74;;7885:2;7870:18;4005:46:11;7751:226:97;461:100:41;;;;;;;;;;-1:-1:-1;541:13:41;461:100;;36074:226:11;;;;;;;;;;;;;:::i;4116:58::-;;;;;;;;;;;;;;;1415:103:41;;;;;;;;;;-1:-1:-1;1499:12:41;1415:103;;2495:604:42;;;;;;;;;;-1:-1:-1;2495:604:42;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;12581:434:11:-;;;;;;;;;;-1:-1:-1;12581:434:11;;;;;:::i;:::-;;:::i;1819:105:41:-;;;;;;;;;;-1:-1:-1;1904:13:41;1819:105;;4232:41:11;;;;;;;;;;-1:-1:-1;4232:41:11;;;;-1:-1:-1;;;;;4232:41:11;;;3168:139;;;;;;;;;;;;;:::i;1181:142:41:-;;;;;;;;;;-1:-1:-1;1181:142:41;;;;;:::i;:::-;-1:-1:-1;;;;;1293:19:41;;:23;;;1181:142;;;;9697:14:97;;9690:22;9672:41;;9660:2;9645:18;1181:142:41;9532:187:97;24212:242:11;;;;;;;;;;-1:-1:-1;24212:242:11;;;;;:::i;:::-;;:::i;25596:978::-;;;;;;;;;;-1:-1:-1;25596:978:11;;;;;:::i;:::-;;:::i;7379:130::-;;;;;;;;;;;;;:::i;1616:109:41:-;;;;;;;;;;-1:-1:-1;1703:15:41;1616:109;;2253:65:2;;;;;;;;;;-1:-1:-1;2253:65:2;;;;;:::i;:::-;;;;;;;;;;;;;;35646:278:11;;;;;;;;;;-1:-1:-1;35646:278:11;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;7179:153::-;;;;;;;;;;-1:-1:-1;7282:7:11;1710:6:78;-1:-1:-1;;;;;1710:6:78;7179:153:11;;5041:62;;;;;;;;;;-1:-1:-1;5041:62:11;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5041:62:11;;;;;;;;10589:25:97;;;10662:10;10650:23;;;10645:2;10630:18;;10623:51;-1:-1:-1;;;;;10710:71:97;;;10690:18;;;10683:99;;;;10813:2;10798:18;;10791:34;10576:3;10561:19;5041:62:11;10360:471:97;4919:64:11;;;;;;;;;;;;;;;5806:2649:2;;;;;;;;;;-1:-1:-1;5806:2649:2;;;;;:::i;:::-;;:::i;20360:854:11:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;5235:75::-;;;;;;;;;;-1:-1:-1;5235:75:11;;;;;:::i;:::-;;;;;;;;;;;;;;980:1198:42;;;;;;;;;;-1:-1:-1;980:1198:42;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;10702:1500:11:-;;;;;;:::i;:::-;;:::i;27795:2319::-;;;;;;;;;;-1:-1:-1;27795:2319:11;;;;;:::i;:::-;;:::i;23722:329::-;;;;;;;;;;-1:-1:-1;23722:329:11;;;;;:::i;:::-;;:::i;31028:1896::-;;;;;;;;;;-1:-1:-1;31028:1896:11;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;3558:137::-;;;;;;;;;;;;;:::i;2128:47:2:-;;;;;;;;;;-1:-1:-1;2128:47:2;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;18099:25:97;;;18155:2;18140:18;;18133:34;;;;18072:18;2128:47:2;17925:248:97;4761:252:2;;;;;;;;;;-1:-1:-1;4761:252:2;;;;;:::i;:::-;;:::i;33825:1665:11:-;;;;;;;;;;-1:-1:-1;33825:1665:11;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;:::i;3887:65::-;;;;;;;;;;;;3946:6;3887:65;;7556:153;;;;;;;;;;-1:-1:-1;7556:153:11;;;;;:::i;:::-;;:::i;682:131:41:-;;;;;;;;;;-1:-1:-1;682:131:41;;;;;:::i;:::-;-1:-1:-1;;;;;791:15:41;;;682:131;15181:1023:11;;;;;;;;;;-1:-1:-1;15181:1023:11;;;;;:::i;:::-;;:::i;22743:229::-;22900:65;;;;;22850:19;;-1:-1:-1;;;;;22914:12:11;22900:54;;;;:65;;22955:9;;;;22900:65;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22881:84;;22743:229;;;;;:::o;13465:545::-;13546:29;13578:63;;;:31;:63;;;;;;;13651:106;;;;-1:-1:-1;;;13651:106:11;;21049:2:97;13651:106:11;;;21031:21:97;21088:2;21068:18;;;21061:30;21127:26;21107:18;;;21100:54;21171:18;;13651:106:11;;;;;;;;;13788:36;;;;:13;:36;;;;;:49;;;13857:15;13788:49;;;;:84;;13767:161;;;;-1:-1:-1;;;13767:161:11;;21402:2:97;13767:161:11;;;21384:21:97;21441:2;21421:18;;;21414:30;21480:32;21460:18;;;21453:60;21530:18;;13767:161:11;21200:354:97;13767:161:11;13938:65;13971:8;13981:21;13938:32;:65::i;:::-;13536:474;13465:545;:::o;8597:843::-;1531:13:78;:11;:13::i;:::-;-1:-1:-1;;;;;8728:32:11;::::1;8707:109;;;::::0;-1:-1:-1;;;8707:109:11;;21761:2:97;8707:109:11::1;::::0;::::1;21743:21:97::0;21800:2;21780:18;;;21773:30;21839:32;21819:18;;;21812:60;21889:18;;8707:109:11::1;21559:354:97::0;8707:109:11::1;8847:17;::::0;-1:-1:-1;;;;;8847:17:11::1;:31:::0;8826:107:::1;;;::::0;-1:-1:-1;;;8826:107:11;;22120:2:97;8826:107:11::1;::::0;::::1;22102:21:97::0;22159:2;22139:18;;;22132:30;22198:31;22178:18;;;22171:59;22247:18;;8826:107:11::1;21918:353:97::0;8826:107:11::1;9272:4;-1:-1:-1::0;;;;;9214:63:11::1;9233:18;-1:-1:-1::0;;;;;9214:44:11::1;;:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;9214:63:11::1;;9193:137;;;::::0;-1:-1:-1;;;9193:137:11;;22734:2:97;9193:137:11::1;::::0;::::1;22716:21:97::0;22773:2;22753:18;;;22746:30;22812:29;22792:18;;;22785:57;22859:18;;9193:137:11::1;22532:351:97::0;9193:137:11::1;9340:17;:38:::0;;;::::1;-1:-1:-1::0;;;;;9340:38:11;::::1;::::0;;::::1;::::0;;;9393:40:::1;::::0;7897:74:97;;;9393:40:11::1;::::0;7885:2:97;7870:18;9393:40:11::1;;;;;;;8597:843:::0;:::o;3863:681:2:-;1531:13:78;:11;:13::i;:::-;3997:8:2;3989:49:::1;;;::::0;-1:-1:-1;;;3989:49:2;;23090:2:97;3989:49:2::1;::::0;::::1;23072:21:97::0;23129:2;23109:18;;;23102:30;23168:16;23148:18;;;23141:44;23202:18;;3989:49:2::1;22888:338:97::0;3989:49:2::1;4071:7:::0;4048:20:::1;4103:17:::0;;;4095:43:::1;;;::::0;-1:-1:-1;;;4095:43:2;;23433:2:97;4095:43:2::1;::::0;::::1;23415:21:97::0;23472:2;23452:18;;;23445:30;23511:15;23491:18;;;23484:43;23544:18;;4095:43:2::1;23231:337:97::0;4095:43:2::1;4178:1;4156:7:::0;;4178:1;4156:10;::::1;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;4156:24:2::1;::::0;4148:62:::1;;;::::0;-1:-1:-1;;;4148:62:2;;23964:2:97;4148:62:2::1;::::0;::::1;23946:21:97::0;24003:2;23983:18;;;23976:30;24042:27;24022:18;;;24015:55;24087:18;;4148:62:2::1;23762:349:97::0;4148:62:2::1;4239:1;4220:194;4248:12;4242:3;:18;4220:194;;;4323:7:::0;;4331::::1;4337:1;4331:3:::0;:7:::1;:::i;:::-;4323:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;4308:31:2::1;:7;;4316:3;4308:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;4308:31:2::1;;4283:120;;;::::0;-1:-1:-1;;;4283:120:2;;24640:2:97;4283:120:2::1;::::0;::::1;24622:21:97::0;24679:2;24659:18;;;24652:30;24718:32;24698:18;;;24691:60;24768:18;;4283:120:2::1;24438:354:97::0;4283:120:2::1;4262:5;;4220:194;;;;4484:7;;4467:25;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;4467:25:2;;::::1;::::0;;;;;;4457:36;;4467:25:::1;4457:36:::0;;::::1;::::0;4423:31:::1;::::0;;;:21:::1;:31:::0;;;;;;:70;4445:8;;4508:29:::1;::::0;::::1;::::0;4529:7;;;;4508:29:::1;:::i;:::-;;;;;;;;3979:565;3863:681:::0;;;:::o;22080:463:11:-;22339:197;;;;;22292:16;;-1:-1:-1;;;;;22353:12:11;22339:54;;;;:197;;22411:7;;22436:10;;22464:9;;22491:4;;;;22513:9;;;;22339:197;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22320:216;22080:463;-1:-1:-1;;;;;;;;22080:463:11:o;18465:758::-;18861:25;18888:22;18939:4;-1:-1:-1;;;;;18939:14:11;;18954:13;;18939:29;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;18939:29:11;;;;;;;;;;;;:::i;:::-;18926:42;;18995:221;19024:8;19046:10;19070:13;19097:16;;19127:8;19149:5;19168:38;;18995:15;:221::i;:::-;18978:238;;18465:758;;;;;;;;;;;;;;:::o;16821:779::-;16993:122;17036:7;17057:12;;17083:22;;16993:29;:122::i;:::-;17299:17;;17280:97;;;;;-1:-1:-1;;;;;7915:55:97;;;17280:97:11;;;7897:74:97;17299:17:11;;;;17280:88;;7870:18:97;;17280:97:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17280:97:11;;;;;;;;;;;;:::i;:::-;17238:161;;;;;;;;:::i;:::-;;;;;;;;;;;;;17207:210;;;;;;17173:12;;17156:30;;;;;;;;;:::i;:::-;;;;;;;;;;;;;17146:41;;;;;;:271;17125:348;;;;-1:-1:-1;;;17125:348:11;;32196:2:97;17125:348:11;;;32178:21:97;32235:2;32215:18;;;32208:30;32274:32;32254:18;;;32247:60;32324:18;;17125:348:11;31994:354:97;17125:348:11;17502:17;;17483:110;;;;;-1:-1:-1;;;;;17502:17:11;;;;17483:53;;:110;;17550:7;;17571:12;;;;17483:110;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16821:779;;;;;:::o;3365:133::-;3453:44;;32938:26:97;3453:44:11;;;32926:39:97;32981:12;;3453:44:11;;;;;;;;;;;;;3443:55;;;;;;3365:133;:::o;36074:226::-;36220:7;5771:53;;;;;;33218:34:97;33206:47;;33283:3;33278:2;33269:12;;33262:25;33312:2;33303:12;;33004:317;5771:53:11;;;;;;;;;;;;;5761:64;;;;;;36243:50;;36074:226;:::o;2495:604:42:-;2605:23;;2691:4;;2724:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2724:21:42;;2712:33;;2780:9;2768:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2755:35;;2805:11;2800:293;2828:9;2822:3;:15;2800:293;;;2962:4;2998;;3003:3;2998:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;2954:67;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2919:9;2929:3;2919:14;;;;;;;;:::i;:::-;;;;;;2935:10;2946:3;2935:15;;;;;;;;:::i;:::-;;;;;;;;;;2918:103;;;;;;;;;3063:5;;2800:293;;;;2661:438;2495:604;;;;;:::o;12581:434:11:-;1531:13:78;:11;:13::i;:::-;12740:1:11::1;12687:41:::0;;;:31:::1;:41;::::0;;;;;12666:126:::1;;;::::0;-1:-1:-1;;;12666:126:11;;21049:2:97;12666:126:11::1;::::0;::::1;21031:21:97::0;21088:2;21068:18;;;21061:30;21127:26;21107:18;;;21100:54;21171:18;;12666:126:11::1;20847:348:97::0;12666:126:11::1;12854:1;12802:41:::0;;;:31:::1;:41;::::0;;;;;:54;;;;12885:17:::1;::::0;12866:96;;-1:-1:-1;;;12866:96:11;;::::1;::::0;::::1;974:25:97::0;;;-1:-1:-1;;;;;12885:17:11;;::::1;::::0;12866:64:::1;::::0;947:18:97;;12866:96:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;12977:31:11::1;::::0;12999:8;;-1:-1:-1;12977:31:11::1;::::0;-1:-1:-1;12977:31:11;;::::1;12581:434:::0;:::o;3168:139::-;3259:47;;34342:29:97;3259:47:11;;;34330:42:97;34388:12;;3259:47:11;34128:278:97;24212:242:11;24373:17;;24354:93;;;;;24311:18;;-1:-1:-1;;;;;24373:17:11;;24354:54;;:93;;24422:15;;;;24354:93;;;:::i;25596:978::-;25703:36;25751:21;25775:34;25793:15;25775:17;:34::i;:::-;25819:39;25917:71;;;:31;:71;;;;;;25751:58;;-1:-1:-1;25819:39:11;25868:700;26002:34;;25868:700;;26156:35;;;;:13;:35;;;;;26227:31;;;;26156:35;;-1:-1:-1;26227:31:11;;26291:15;26276:30;;26272:286;;;26437:29;;;;26490:6;;26437:29;;;-1:-1:-1;;;;;26437:29:11;26380;26395:14;26380:12;:29;:::i;:::-;26379:87;;;;;;:::i;:::-;26378:118;;;;:::i;:::-;26326:170;;-1:-1:-1;;;;;26326:170:11;;;:::i;:::-;;;26531:12;26514:29;;26272:286;-1:-1:-1;;26073:37:11;;;;25868:700;;;;25741:833;;25596:978;;;:::o;7379:130::-;7463:39;;-1:-1:-1;;;7463:39:11;;36056:2:97;7463:39:11;;;36038:21:97;36095:2;36075:18;;;36068:30;36134:31;36114:18;;;36107:59;36183:18;;7463:39:11;35854:353:97;35646:278:11;35816:101;35857:29;;;:13;:29;;;;;;;;:50;35816:101;;:27;:101;;;;;35797:120;;35756:29;;35816:101;35797:120;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35646:278;;;:::o;5806:2649:2:-;5991:9;5983:51;;;;-1:-1:-1;;;5983:51:2;;36856:2:97;5983:51:2;;;36838:21:97;36895:2;36875:18;;;36868:30;36934:17;36914:18;;;36907:45;36969:18;;5983:51:2;36654:339:97;5983:51:2;6069:15;6052:13;:32;;6044:71;;;;-1:-1:-1;;;6044:71:2;;37200:2:97;6044:71:2;;;37182:21:97;37239:2;37219:18;;;37212:30;37278:28;37258:18;;;37251:56;37324:18;;6044:71:2;36998:350:97;6044:71:2;6162:16;;;;:6;:16;;;;;;;;:26;;6146:42;;6125:119;;;;-1:-1:-1;;;6125:119:2;;37555:2:97;6125:119:2;;;37537:21:97;37594:2;37574:18;;;37567:30;37633:32;37613:18;;;37606:60;37683:18;;6125:119:2;37353:354:97;6125:119:2;6254:19;6276:31;;;:21;:31;;;;;;;6317:53;;;;-1:-1:-1;;;6317:53:2;;37914:2:97;6317:53:2;;;37896:21:97;37953:2;37933:18;;;37926:30;37992:17;37972:18;;;37965:45;38027:18;;6317:53:2;37712:339:97;6317:53:2;6406:10;6380:23;6406:10;6460:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6460:30:2;-1:-1:-1;6594:52:2;;;;;;38241:19:97;;;38276:12;;;38269:28;;;38313:12;;;38306:28;;;6433:57:2;;-1:-1:-1;6500:28:2;;6531:126;;38350:12:97;;6594:52:2;;;;;;;;;;;;;6584:63;;;;;;1403:34:92;1298:14;1390:48;;;1499:4;1492:25;;;;1597:4;1581:21;;;1222:460;6531:126:2;6500:157;;6672:11;6667:1512;6695:15;6689:3;:21;6667:1512;;;6733:23;6759:10;;6770:3;6759:15;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:22;-1:-1:-1;;;;6799:41:2;;6795:1374;;6875:110;6910:20;6952:10;;6963:3;6952:15;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;6875:110;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6875:13:2;;-1:-1:-1;;;6875:110:2:i;:::-;6860:7;6868:3;6860:12;;;;;;;;:::i;:::-;;;;;;:125;-1:-1:-1;;;;;6860:125:2;;;-1:-1:-1;;;;;6860:125:2;;;;;6795:1374;;;2616:36;7010:15;:45;7006:1163;;7097:30;7149:32;7203:26;7261:10;;7272:3;7261:15;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;7250:52;;;;;;;:::i;:::-;7075:227;;;;;;7367:22;7349:15;:40;7320:127;;;;-1:-1:-1;;;7320:127:2;;39719:2:97;7320:127:2;;;39701:21:97;39758:2;39738:18;;;39731:30;39797:18;39777;;;39770:46;39833:18;;7320:127:2;39517:340:97;7320:127:2;7480:601;7515:507;7669:29;:27;:29::i;:::-;7732:156;7783:20;7841:13;7732;:156::i;:::-;7922:22;7619:355;;;;;;;;;40047:19:97;;;40104:2;40100:15;;;;-1:-1:-1;;40096:53:97;40091:2;40082:12;;40075:75;40175:2;40166:12;;40159:28;40212:2;40203:12;;39862:359;7515:507:2;8044:19;7480:13;:601::i;:::-;7465:7;7473:3;7465:12;;;;;;;;:::i;:::-;;;;;;:616;-1:-1:-1;;;;;7465:616:2;;;-1:-1:-1;;;;;7465:616:2;;;;;7057:1039;;;7006:1163;;;8120:34;;-1:-1:-1;;;8120:34:2;;40428:2:97;8120:34:2;;;40410:21:97;40467:2;40447:18;;;40440:30;40506:26;40486:18;;;40479:54;40550:18;;8120:34:2;40226:348:97;7006:1163:2;-1:-1:-1;6712:5:2;;6667:1512;;;;8251:7;8234:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;8224:36;;;;;;8209:11;:51;8188:116;;;;-1:-1:-1;;;8188:116:2;;41361:2:97;8188:116:2;;;41343:21:97;41400:2;41380:18;;;41373:30;41439:20;41419:18;;;41412:48;41477:18;;8188:116:2;41159:342:97;8188:116:2;8333:50;;;;;;;;;;;;;;;;;;-1:-1:-1;8314:16:2;;;:6;:16;;;;;;;:69;;;;;;;;8398:50;8321:8;;8398:50;;;;8346:9;;8368:13;;18099:25:97;;;18155:2;18140:18;;18133:34;18087:2;18072:18;;17925:248;8398:50:2;;;;;;;;5973:2482;;;;5806:2649;;;;;:::o;20360:854:11:-;20775:23;20812:25;20851:22;20924:4;-1:-1:-1;;;;;20924:17:11;;20942:16;;20924:35;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;20924:35:11;;;;;;;;;;;;:::i;:::-;20898:61;;-1:-1:-1;20898:61:11;-1:-1:-1;20986:221:11;21015:8;21037:10;21061:13;21088:16;;21118:8;21140:5;21159:38;;20986:15;:221::i;:::-;20969:238;;20360:854;;;;;;;;;;;;;;;:::o;980:1198:42:-;1063:25;1120:4;;1154:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1141:35;;1191:11;1186:986;1214:9;1208:3;:15;1186:986;;;1241:12;1367:4;1386;;1391:3;1386:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;1359:37;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1340:10;1351:3;1340:15;;;;;;;;:::i;:::-;;;;;;;;;;1330:66;;-1:-1:-1;1330:66:42;1410:691;;1442:37;1482:10;1493:3;1482:15;;;;;;;;:::i;:::-;;;;;;;1442:55;;1553:1;1519:24;:31;:35;1515:572;;;1773:24;1767:31;1922:15;1867:24;1863:2;1859:33;1823:140;1515:572;2031:37;;-1:-1:-1;;;2031:37:42;;43039:2:97;2031:37:42;;;43021:21:97;43078:2;43058:18;;;43051:30;43117:29;43097:18;;;43090:57;43164:18;;2031:37:42;42837:351:97;1410:691:42;-1:-1:-1;2142:5:42;;1186:986;;;;1090:1088;980:1198;;;;:::o;10702:1500:11:-;11012:22;11054:10;11046:54;;;;-1:-1:-1;;;11046:54:11;;43395:2:97;11046:54:11;;;43377:21:97;43434:2;43414:18;;;43407:30;43473:19;43453:18;;;43446:47;43510:18;;11046:54:11;43193:341:97;11046:54:11;-1:-1:-1;;;;;11118:27:11;;11110:67;;;;-1:-1:-1;;;11110:67:11;;43741:2:97;11110:67:11;;;43723:21:97;43780:2;43760:18;;;43753:30;43819:29;43799:18;;;43792:57;43866:18;;11110:67:11;43539:351:97;11110:67:11;11187:252;11247:8;11269:10;11293:13;11320:16;;11350:8;11372:5;11391:38;;11187:46;:252::i;:::-;11466:149;11502:8;11524:10;11548:16;;11578:8;11600:5;11466:22;:149::i;:::-;11449:166;;11699:45;11735:8;11699:35;:45::i;:::-;11646:33;11670:9;-1:-1:-1;;;;;11646:21:11;;;:33;:::i;:::-;:98;;11625:165;;;;-1:-1:-1;;;11625:165:11;;44097:2:97;11625:165:11;;;44079:21:97;44136:2;44116:18;;;44109:30;44175:22;44155:18;;;44148:50;44215:18;;11625:165:11;43895:344:97;11625:165:11;11859:14;11837:8;11805:223;11887:10;11911:13;11938:16;;11968:8;11990:5;12009:9;11805:223;;;;;;;;;;;;:::i;:::-;;;;;;;;12042:9;:13;12038:158;;12072:12;12090:13;-1:-1:-1;;;;;12090:18:11;12116:9;12090:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12071:59;;;12152:7;12144:41;;;;-1:-1:-1;;;12144:41:11;;45321:2:97;12144:41:11;;;45303:21:97;45360:2;45340:18;;;45333:30;45399:23;45379:18;;;45372:51;45440:18;;12144:41:11;45119:345:97;12144:41:11;12057:139;12038:158;10702:1500;;;;;;;;;;;:::o;27795:2319::-;28018:36;5663:12;28087:51;;28066:130;;;;-1:-1:-1;;;28066:130:11;;45671:2:97;28066:130:11;;;45653:21:97;;;45690:18;;;45683:30;45749:34;45729:18;;;45722:62;45801:18;;28066:130:11;45469:356:97;28066:130:11;28220:22;28256:19;28289:30;28333:26;28372:135;28425:8;28451:16;;28485:8;28372:35;:135::i;:::-;28206:301;;;;;;;;28517:18;28557:8;28539:5;28547:6;28539:14;;;;:::i;:::-;28538:27;;;;:::i;:::-;28517:48;;28575:21;28599:34;28617:15;28599:17;:34::i;:::-;28575:58;-1:-1:-1;28643:28:11;28674:36;;:121;;28754:41;;;;:31;:41;;;;;;28674:121;;;28725:14;28674:121;28643:152;;28805:1303;28812:34;;28805:1303;;28892:14;28868:20;:38;28864:1234;;29047:6;29013:10;28980:29;28995:14;28980:12;:29;:::i;:::-;28979:44;;;;;;:::i;:::-;28978:75;;;;:::i;:::-;28926:127;;;;:::i;:::-;;;29088:12;29071:29;;29141:18;29118:41;;28805:1303;;28864:1234;29198:39;29240:73;;;:13;:73;;;;;29371:52;;;;;;29478:15;29445:48;;29441:364;;;29654:29;;;;29711:6;;29654:29;;;-1:-1:-1;;;;;29654:29:11;29575:47;29608:14;29575:30;:47;:::i;:::-;29574:109;;;;;;:::i;:::-;29573:144;;;;:::i;:::-;29517:200;;-1:-1:-1;;;;;29517:200:11;;;:::i;:::-;;;29756:30;29739:47;;29441:364;29852:20;29826:22;:46;29822:262;;29919:14;29896:37;;29822:262;;;30003:18;:62;;;29980:85;;29822:262;29180:918;;28805:1303;;;28056:2058;;;;;;;27795:2319;;;;;;;:::o;23722:329::-;23928:116;;;;;23871:25;;-1:-1:-1;;;;;23954:24:11;23928:88;;;;:116;;24017:8;;24027:6;;24035:8;;;;23928:116;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23908:136;23722:329;-1:-1:-1;;;;;23722:329:11:o;31028:1896::-;31158:28;31200:16;31230:20;31264:28;31306:32;31352:31;31397:29;31440:28;31493:25;31535:12;-1:-1:-1;;;;;31521:65:11;;31614:8;31597:26;;;;;;46648:19:97;;46692:2;46683:12;;46519:182;31597:26:11;;;;;;;;;;;;;31587:37;;;;;;31521:104;;;;;;;;;;;;;974:25:97;;962:2;947:18;;828:177;31521:104:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31493:132;;31783:34;31799:17;31783:15;:34::i;:::-;31827:19;31909:71;;;:31;:71;;;;;;31635:182;;-1:-1:-1;31635:182:11;;-1:-1:-1;31635:182:11;;-1:-1:-1;31635:182:11;-1:-1:-1;31635:182:11;-1:-1:-1;31827:19:11;31860:325;31994:34;;31860:325;;32161:13;;;;:::i;:::-;32065:35;;;;:13;:35;;;;;;:71;;;32161:13;;-1:-1:-1;31860:325:11;;-1:-1:-1;31860:325:11;;;32225:11;32213:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32194:43;;32276:11;32263:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32263:25:11;;32247:41;;32326:11;32312:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32312:26:11;-1:-1:-1;32348:39:11;32417:41;;;:31;:41;;;;;;;;;32390:78;;:13;:78;;;;;32298:40;;-1:-1:-1;32478:440:11;32506:11;32500:3;:17;32478:440;;;32609:39;;32564:98;;;;:27;:98;;;;;32540:122;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;32557:3;32540:21;;;;;;;;:::i;:::-;;;;;;;;;;:122;32697:31;;;;32676:18;;32697:31;;;;;32676:13;;32690:3;;32676:18;;;;;;:::i;:::-;;;;;;:52;;;;;;;;;;;32761:18;:29;;;;;;;;;;-1:-1:-1;;;;;32761:29:11;32742:11;32754:3;32742:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32742:48:11;;;:16;;;;;;;;;;:48;32856:37;;;;;32825:82;;;;:13;:82;;;;;;;;32519:5;;32478:440;;;;31483:1441;;;31028:1896;;;;;;;;;:::o;3558:137::-;3648:46;;47060:28:97;3648:46:11;;;47048:41:97;47105:12;;3648:46:11;46846:277:97;4761:252:2;1531:13:78;:11;:13::i;:::-;4894:52:2::1;::::0;;;;::::1;::::0;;;;;4929:15:::1;4894:52;::::0;;::::1;::::0;;;-1:-1:-1;4875:16:2;;;:6:::1;:16:::0;;;;;;;:71;;;;;;;::::1;::::0;;;;4961:45;;18099:25:97;;;18140:18;;;18133:34;4875:16:2;;4961:45:::1;::::0;18072:18:97;4961:45:2::1;;;;;;;4761:252:::0;;:::o;33825:1665:11:-;34192:17;;34173:82;;;;;;;;974:25:97;;;33942:28:11;;33984:20;;;;33942:28;;;;-1:-1:-1;;;;;34192:17:11;;34173:70;;947:18:97;;34173:82:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;34173:82:11;;;;;;;;;;;;:::i;:::-;34302:62;;-1:-1:-1;;;34302:62:11;;;;;974:25:97;;;34155:100:11;;-1:-1:-1;34316:12:11;-1:-1:-1;;;;;34302:50:11;;;;947:18:97;;34302:62:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34391:22;;34265:99;;-1:-1:-1;34265:99:11;-1:-1:-1;;;34391:68:11;34374:1110;;34499:15;;;34512:1;34499:15;;;;;;;;;;;;;;;;;;;-1:-1:-1;;34547:15:11;;;34560:1;34547:15;;;;;;;;;34484:30;;-1:-1:-1;34560:1:11;-1:-1:-1;34547:15:11;;;;;;;;;;;-1:-1:-1;34547:15:11;34528:34;;34577:15;34594:18;34644:15;34616:93;;;;;;;;;;;;:::i;:::-;34576:133;;;;34778:12;-1:-1:-1;;;;;34764:54:11;;34819:35;34834:7;34843:10;52303:37;;-1:-1:-1;;61017:2:97;61013:15;;;61009:53;52303:37:11;;;60997:66:97;61079:12;;;61072:28;;;52254:16:11;;61116:12:97;;52303:37:11;;;;;;;;;;;;52293:48;;;;;;52282:59;;52149:199;;;;;34819:35;34764:91;;;;;;;;;;;;;974:25:97;;962:2;947:18;;828:177;34764:91:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34724:12;34737:1;34724:15;;;;;;;;:::i;:::-;;;;;;34741:16;34758:1;34741:19;;;;;;;;:::i;:::-;;;;;;34723:132;;;;;;;;;;;;;;;;;;34470:396;;34374:1110;;;34876:22;;:27;34872:612;;34920:25;34947:28;35007:15;34979:68;;;;;;;;;;;;:::i;:::-;35083:15;;34919:128;;-1:-1:-1;34919:128:11;-1:-1:-1;35083:15:11;35127:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35127:25:11;;35112:40;;35198:11;35185:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35185:25:11;;35166:44;;35229:11;35224:250;35252:11;35246:3;:17;35224:250;;;35370:12;-1:-1:-1;;;;;35335:75:11;;35411:47;35426:8;35435:3;35426:13;;;;;;;;:::i;:::-;;;;;;;35441:11;35453:3;35441:16;;;;;;;;:::i;:::-;;;;;;;52303:37;;-1:-1:-1;;61017:2:97;61013:15;;;61009:53;52303:37:11;;;60997:66:97;61079:12;;;61072:28;;;52254:16:11;;61116:12:97;;52303:37:11;;;;;;;;;;;;52293:48;;;;;;52282:59;;52149:199;;;;;35411:47;35335:124;;;;;;;;;;;;;974:25:97;;962:2;947:18;;828:177;35335:124:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35291:12;35304:3;35291:17;;;;;;;;:::i;:::-;;;;;;35310:16;35327:3;35310:21;;;;;;;;:::i;:::-;35290:169;;;;35310:21;;;;;;;;;;;35290:169;;;;;;;;;;;35265:5;;35224:250;;;;34905:579;;;34872:612;33825:1665;;;;;;;:::o;7556:153::-;7661:41;;-1:-1:-1;;;7661:41:11;;50526:2:97;7661:41:11;;;50508:21:97;50565:2;50545:18;;;50538:30;50604:33;50584:18;;;50577:61;50655:18;;7661:41:11;50324:355:97;15181:1023:11;15377:24;;15373:270;;-1:-1:-1;;;;;15425:27:11;;15417:67;;;;-1:-1:-1;;;15417:67:11;;43741:2:97;15417:67:11;;;43723:21:97;43780:2;43760:18;;;43753:30;43819:29;43799:18;;;43792:57;43866:18;;15417:67:11;43539:351:97;15417:67:11;15373:270;;;-1:-1:-1;;;;;15540:27:11;;;15515:117;;;;-1:-1:-1;;;15515:117:11;;50886:2:97;15515:117:11;;;50868:21:97;50925:2;50905:18;;;50898:30;50964:33;50944:18;;;50937:61;51015:18;;15515:117:11;50684:355:97;15515:117:11;15652:152;15697:8;15719:10;15743:13;15770:24;;15652:31;:152::i;:::-;15814:25;15856:12;-1:-1:-1;;;;;15842:65:11;;15935:8;15918:26;;;;;;46648:19:97;;46692:2;46683:12;;46519:182;15918:26:11;;;;;;;;;;;;;15908:37;;;;;;15842:104;;;;;;;;;;;;;974:25:97;;962:2;947:18;;828:177;15842:104:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15814:132;;15985:10;15964:17;:31;15956:69;;;;-1:-1:-1;;;15956:69:11;;51246:2:97;15956:69:11;;;51228:21:97;51285:2;51265:18;;;51258:30;51324:27;51304:18;;;51297:55;51369:18;;15956:69:11;51044:349:97;15956:69:11;16039:24;;16035:92;;16079:37;16105:10;16079:25;:37::i;:::-;16136:61;;-1:-1:-1;;;16136:61:11;;;;;18099:25:97;;;18140:18;;;18133:34;;;16150:12:11;-1:-1:-1;;;;;16136:39:11;;;;18072:18:97;;16136:61:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15363:841;15181:1023;;;;;:::o;39348:971::-;39479:295;39520:36;;;;:13;:36;;;;;:72;;;39624:35;;;;;:139;;-1:-1:-1;39679:36:11;;;;:13;:36;;;;;:49;;;39748:15;39679:49;;;;:84;;39624:139;39479:295;;39788:61;;39827:21;;39817:8;;39788:61;;;;;39859:41;;;;:31;:41;;;;;:65;;;39903:21;39934:379;;40008:17;;39989:104;;-1:-1:-1;;;39989:104:11;;;;;974:25:97;;;-1:-1:-1;;;;;40008:17:11;;;;39989:64;;947:18:97;;39989:104:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13536:474;13465:545;:::o;39934:379::-;40143:17;;-1:-1:-1;;;;;40143:17:11;40124:65;40207:8;40233:55;40266:21;40233:32;:55::i;:::-;40124:178;;;;;;;;;;;;;;;;:::i;1796:162:78:-;735:10:86;1855:7:78;7282::11;1710:6:78;-1:-1:-1;;;;;1710:6:78;;7179:153:11;1855:7:78;-1:-1:-1;;;;;1855:23:78;;1851:101;;1901:40;;;;;735:10:86;1901:40:78;;;7897:74:97;7870:18;;1901:40:78;7751:226:97;1851:101:78;1796:162::o;51131:821:11:-;51323:30;;51420:56;;;;51431:22;51420:56;:::i;:::-;51309:167;;;;51577:22;51507:6;:44;3648:46;;;;;;47060:28:97;47048:41;;47114:2;47105:12;;46846:277;3648:46:11;;;;;;;;;;;;;3638:57;;;;;;51507:44;;;;;;;;;;;:50;;;:92;51486:151;;;;-1:-1:-1;;;51486:151:11;;53339:2:97;51486:151:11;;;53321:21:97;53378:2;53358:18;;;53351:30;-1:-1:-1;;;53397:18:97;;;53390:42;53449:18;;51486:151:11;53137:336:97;51486:151:11;51668:238;51704:23;51745:22;51850:7;51859:12;;51839:33;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;51839:33:11;;;;;;;;;51829:44;;51839:33;51829:44;;;;51816:58;;;46648:19:97;46683:12;51816:58:11;;;;;;;;;;;;51785:107;;;;;;51668:18;:238::i;:::-;51647:298;;;;-1:-1:-1;;;51647:298:11;;53680:2:97;51647:298:11;;;53662:21:97;53719:2;53699:18;;;53692:30;-1:-1:-1;;;53738:18:97;;;53731:43;53791:18;;51647:298:11;53478:337:97;51647:298:11;51299:653;;51131:821;;;;;:::o;15291:213:94:-;15347:6;15377:16;15369:24;;15365:103;;;15416:41;;-1:-1:-1;;;15416:41:94;;15447:2;15416:41;;;54001:36:97;54053:18;;;54046:34;;;53974:18;;15416:41:94;53820:266:97;15365:103:94;-1:-1:-1;15491:5:94;15291:213::o;3702:255:90:-;3780:7;3800:17;3819:18;3839:16;3859:27;3870:4;3876:9;3859:10;:27::i;:::-;3799:87;;;;;;3896:28;3908:5;3915:8;3896:11;:28::i;:::-;-1:-1:-1;3941:9:90;;3702:255;-1:-1:-1;;;;3702:255:90:o;48540:2351:11:-;48871:8;48863:49;;;;-1:-1:-1;;;48863:49:11;;54293:2:97;48863:49:11;;;54275:21:97;54332:2;54312:18;;;54305:30;54371:16;54351:18;;;54344:44;54405:18;;48863:49:11;54091:338:97;48863:49:11;5663:12;48943:51;;48922:130;;;;-1:-1:-1;;;48922:130:11;;45671:2:97;48922:130:11;;;45653:21:97;;;45690:18;;;45683:30;45749:34;45729:18;;;45722:62;45801:18;;48922:130:11;45469:356:97;48922:130:11;49070:8;49082:1;49070:13;49062:39;;;;-1:-1:-1;;;49062:39:11;;54636:2:97;49062:39:11;;;54618:21:97;54675:2;54655:18;;;54648:30;54714:15;54694:18;;;54687:43;54747:18;;49062:39:11;54434:337:97;49062:39:11;49119:5;49128:1;49119:10;49111:33;;;;-1:-1:-1;;;49111:33:11;;54978:2:97;49111:33:11;;;54960:21:97;55017:2;54997:18;;;54990:30;55056:12;55036:18;;;55029:40;55086:18;;49111:33:11;54776:334:97;49111:33:11;49168:32;;;;49365:138;;;;49393:38;49365:138;:::i;:::-;49154:349;;;;;;;;49605:24;49534:6;:45;3259:47;;;;;;34342:29:97;34330:42;;34397:2;34388:12;;34128:278;3259:47:11;;;;;;;;;;;;;3249:58;;;;;;49534:45;;;;;;;;;;;:51;;;:95;49513:154;;;;-1:-1:-1;;;49513:154:11;;53339:2:97;49513:154:11;;;53321:21:97;53378:2;53358:18;;;53351:30;-1:-1:-1;;;53397:18:97;;;53390:42;53449:18;;49513:154:11;53137:336:97;49513:154:11;49927:47;;;;;;56147:25:97;;;56188:18;;;56181:34;;;-1:-1:-1;;;;;56251:55:97;;56231:18;;;56224:83;49698:356:11;;49734:25;;49777:24;;56120:18:97;;49927:47:11;55945:368:97;49698:356:11;49677:416;;;;-1:-1:-1;;;49677:416:11;;53680:2:97;49677:416:11;;;53662:21:97;53719:2;53699:18;;;53692:30;-1:-1:-1;;;53738:18:97;;;53731:43;53791:18;;49677:416:11;53478:337:97;49677:416:11;50192:21;50124:6;:42;3453:44;;;;;;32938:26:97;32926:39;;32990:2;32981:12;;32724:275;3453:44:11;;;;;;;;;;;;;3443:55;;;;;;50124:42;;;;;;;;;;;:48;;;:89;50103:148;;;;-1:-1:-1;;;50103:148:11;;53339:2:97;50103:148:11;;;53321:21:97;53378:2;53358:18;;;53351:30;-1:-1:-1;;;53397:18:97;;;53390:42;53449:18;;50103:148:11;53137:336:97;50103:148:11;50282:563;50318:22;50358:21;50549:8;50591:13;50638:16;;50688:8;50730:5;50505:260;;;;;;;;;;;;;:::i;50282:563::-;50261:623;;;;-1:-1:-1;;;50261:623:11;;53680:2:97;50261:623:11;;;53662:21:97;53719:2;53699:18;;;53692:30;-1:-1:-1;;;53738:18:97;;;53731:43;53791:18;;50261:623:11;53478:337:97;50261:623:11;48853:2038;;;;48540:2351;;;;;;;;;:::o;36580:2563::-;36780:22;36814:19;36843:30;36883:26;37054:119;37103:8;37125:16;;37155:8;37054:35;:119::i;:::-;37214:27;;36919:254;;-1:-1:-1;36919:254:11;;-1:-1:-1;36919:254:11;-1:-1:-1;36919:254:11;-1:-1:-1;37183:28:11;;37214:27;;37224:16;;;;37214:27;:::i;:::-;;;;;;;;37183:58;;37255:27;:49;37283:20;37255:49;;;;;;;;;;;:56;;;;;:::i;:::-;;;37315:1;37255:61;37251:190;;37332:79;;;;:27;:79;;;;;:98;37414:16;;37332:79;:98;:::i;:::-;;37251:190;37482:245;;;;;;;;;;;;;;;;;;;;;37617:47;37655:8;37637:14;:5;37645:6;37637:14;:::i;:::-;37636:27;;;;:::i;:::-;37617:18;:47::i;:::-;-1:-1:-1;;;;;37482:245:11;;;;;;;;;;;;-1:-1:-1;37450:29:11;;;:13;:29;;;;;;;:277;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37741:22;37737:1095;;37815:41;;;;:31;:41;;;;;;37797:59;;37793:233;;37881:54;;37920:14;;37910:8;;37881:54;;;;;37953:41;;;;:31;:41;;;;;:58;;;37793:233;38058:17;;38039:139;;;;;-1:-1:-1;;;;;38058:17:11;;;;38039:65;;:139;;38122:8;;38148:16;;;;38039:139;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;38211:17:11;;38192:102;;;;;;;;974:25:97;;;-1:-1:-1;;;;;38211:17:11;;;;-1:-1:-1;38192:62:11;;-1:-1:-1;947:18:97;;38192:102:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37737:1095;;;38325:37;;;;:13;:37;;;;;;;;:73;;:90;;;38461:71;;;:31;:71;;;;;;38567:36;;;;;;;;;;:49;;;38636:15;38567:49;;;;:84;38546:276;;38684:123;38738:8;38768:21;38684:32;:123::i;:::-;38311:521;37737:1095;38841:37;38867:10;38841:25;:37::i;:::-;39030:10;38919:12;-1:-1:-1;;;;;38905:52:11;;39002:8;38985:26;;;;;;46648:19:97;;46692:2;46683:12;;46519:182;38985:26:11;;;;;;;;;;;;;38975:37;;;;;;38905:121;;;;;;;;;;;;;974:25:97;;962:2;947:18;;828:177;38905:121:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:135;38888:249;;39065:61;;-1:-1:-1;;;39065:61:11;;;;;18099:25:97;;;18140:18;;;18133:34;;;39079:12:11;-1:-1:-1;;;;;39065:39:11;;;;18072:18:97;;39065:61:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38888:249;36804:2339;;;;36580:2563;;;;;;;;:::o;41183:2956::-;41386:22;41422:19;41455:30;41499:26;41607:8;41627:16;;41617:27;;;;;;;:::i;:::-;;;;;;;;;41590:55;;;;;59356:19:97;;;59400:2;59391:12;;59384:28;59437:2;59428:12;;59199:247;41590:55:11;;;;;;;;;;;;;41567:88;;;;;;41550:105;;41680:45;41716:8;41698:15;:26;;;;:::i;:::-;41680:17;:45::i;:::-;41665:60;-1:-1:-1;41749:38:11;;;41878:56;;;;41889:16;41878:56;:::i;:::-;41944:22;42078:71;;;:31;:71;;;;;;41735:199;;-1:-1:-1;41735:199:11;;-1:-1:-1;41735:199:11;-1:-1:-1;41944:22:11;;;42029:1977;42163:34;;42029:1977;;42317:35;;;;:13;:35;;;;;42620:39;;42317:35;;-1:-1:-1;42434:243:11;;42489:30;;42541:18;;42581:17;;42434:33;:243::i;:::-;42731:48;;;;;42366:311;;-1:-1:-1;42731:48:11;;;;;42818:32;:105;;;;;;;;:::i;:::-;;:174;;;;42962:30;42947:45;;:12;:45;;;42818:174;42793:262;;;;-1:-1:-1;;;42793:262:11;;60332:2:97;42793:262:11;;;60314:21:97;60371:2;60351:18;;;60344:30;60410:31;60390:18;;;60383:59;60459:18;;42793:262:11;60130:353:97;42793:262:11;43142:48;43090:32;:100;;;;;;;;:::i;:::-;;:168;;;;;43243:15;43210:30;:48;;;43090:168;43069:316;;;43316:20;43291:45;;43354:16;;;;;:::i;:::-;;;;43069:316;43471:49;43419:32;:101;;;;;;;;:::i;:::-;;:166;;;;;43555:30;43540:45;;:12;:45;;;43419:166;43398:598;;;43639:20;43618:41;;43677:282;43725:34;;43677:282;;43924:16;;;;:::i;:::-;43804:35;;;;:13;:35;;;;;;:79;;;43924:16;;-1:-1:-1;43677:282:11;;-1:-1:-1;43677:282:11;;43976:5;;;;43398:598;-1:-1:-1;;;42234:37:11;;;;42029:1977;;;;44053:30;44036:14;:47;44015:117;;;;-1:-1:-1;;;44015:117:11;;60690:2:97;44015:117:11;;;60672:21:97;60729:2;60709:18;;;60702:30;60768:25;60748:18;;;60741:53;60811:18;;44015:117:11;60488:347:97;44015:117:11;41540:2599;;;;;41183:2956;;;;;;;;;:::o;47501:1033::-;47713:8;47705:49;;;;-1:-1:-1;;;47705:49:11;;54293:2:97;47705:49:11;;;54275:21:97;54332:2;54312:18;;;54305:30;54371:16;54351:18;;;54344:44;54405:18;;47705:49:11;54091:338:97;47705:49:11;47778:32;;47879:58;;;;47890:24;47879:58;:::i;:::-;47764:173;;;;48039:24;47968:6;:45;3259:47;;;;;;34342:29:97;34330:42;;34397:2;34388:12;;34128:278;3259:47:11;;;;;;;;;;;;;3249:58;;;;;;47968:45;;;;;;;;;;;:51;;;:95;47947:154;;;;-1:-1:-1;;;47947:154:11;;53339:2:97;47947:154:11;;;53321:21:97;53378:2;53358:18;;;53351:30;-1:-1:-1;;;53397:18:97;;;53390:42;53449:18;;47947:154:11;53137:336:97;47947:154:11;48361:47;;;;;;56147:25:97;;;56188:18;;;56181:34;;;-1:-1:-1;;;;;56251:55:97;;56231:18;;;56224:83;48132:356:11;;48168:25;;48211:24;;56120:18:97;;48361:47:11;55945:368:97;46722:492:11;46823:71;;-1:-1:-1;;;46823:71:11;;;;;974:25:97;;;46803:16:11;;46837:12;-1:-1:-1;;;;;46823:37:11;;;;947:18:97;;46823:71:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46800:94;-1:-1:-1;46944:35:11;;-1:-1:-1;3946:6:11;46944:35;;;;:::i;:::-;46925:15;:54;;46904:122;;;;-1:-1:-1;;;46904:122:11;;61341:2:97;46904:122:11;;;61323:21:97;61380:2;61360:18;;;61353:30;61419:23;61399:18;;;61392:51;61460:18;;46904:122:11;61139:345:97;46904:122:11;47076:17;;47057:100;;;;;;;;974:25:97;;;-1:-1:-1;;;;;47076:17:11;;;;47057:58;;947:18:97;;47057:100:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47036:171;;;;-1:-1:-1;;;47036:171:11;;61898:2:97;47036:171:11;;;61880:21:97;61937:2;61917:18;;;61910:30;61976:26;61956:18;;;61949:54;62020:18;;47036:171:11;61696:348:97;1265:154:91;1356:4;1408;1379:25;1392:5;1399:4;1379:12;:25::i;:::-;:33;1372:40;;1265:154;;;;;;:::o;2129:766:90:-;2210:7;2219:12;2233:7;2256:9;:16;2276:2;2256:22;2252:637;;2592:4;2577:20;;2571:27;2641:4;2626:20;;2620:27;2698:4;2683:20;;2677:27;2294:9;2669:36;2739:25;2750:4;2669:36;2571:27;2620;2739:10;:25::i;:::-;2732:32;;;;;;;;;;;2252:637;-1:-1:-1;;2860:16:90;;2811:1;;-1:-1:-1;2815:35:90;;2252:637;2129:766;;;;;:::o;7196:532::-;7291:20;7282:5;:29;;;;;;;;:::i;:::-;;7278:444;;7196:532;;:::o;7278:444::-;7387:29;7378:5;:38;;;;;;;;:::i;:::-;;7374:348;;7439:23;;;;;;;;;;;;;;7374:348;7492:35;7483:5;:44;;;;;;;;:::i;:::-;;7479:243;;7550:46;;;;;;;;974:25:97;;;947:18;;7550:46:90;828:177:97;7479:243:90;7626:30;7617:5;:39;;;;;;;;:::i;:::-;;7613:109;;7679:32;;;;;;;;974:25:97;;;947:18;;7679:32:90;828:177:97;3151:218:94;3208:7;-1:-1:-1;;;;;3231:25:94;;3227:105;;;3279:42;;-1:-1:-1;;;3279:42:94;;3310:3;3279:42;;;54001:36:97;54053:18;;;54046:34;;;53974:18;;3279:42:94;53820:266:97;44561:1914:11;44794:32;45159:55;;;:27;:55;;;;;45131:141;;44794:32;;;;;;45159:55;45131:141;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44970:302;;;;;;45325:24;45303:46;;:18;:46;;;45282:123;;;;-1:-1:-1;;;45282:123:11;;63003:2:97;45282:123:11;;;62985:21:97;63042:2;63022:18;;;63015:30;63081:32;63061:18;;;63054:60;63131:18;;45282:123:11;62801:354:97;45282:123:11;45483:36;45433:30;:86;45432:150;;;;;45558:23;45537:17;:44;45432:150;45415:1054;;;45614:46;45607:53;;;;;;;45415:1054;45745:36;45695:30;:86;;45694:150;;;;;45820:23;45799:17;:44;;45694:150;45677:792;;;45876:49;45869:56;;;;;;;45677:792;46010:36;45960:30;:86;;45959:150;;;;;46085:23;46064:17;:44;;45959:150;45942:527;;;46141:48;46134:55;;;;;;;45942:527;46418:40;;-1:-1:-1;;;46418:40:11;;63362:2:97;46418:40:11;;;63344:21:97;63401:2;63381:18;;;63374:30;63440:32;63420:18;;;63413:60;63490:18;;46418:40:11;63160:354:97;44561:1914:11;;;;;;;:::o;1967:290:91:-;2050:7;2092:4;2050:7;2106:116;2130:5;:12;2126:1;:16;2106:116;;;2178:33;2188:12;2202:5;2208:1;2202:8;;;;;;;;:::i;:::-;;;;;;;2178:9;:33::i;:::-;2163:48;-1:-1:-1;2144:3:91;;2106:116;;;-1:-1:-1;2238:12:91;1967:290;-1:-1:-1;;;1967:290:91:o;5140:1530:90:-;5266:7;;;6199:66;6186:79;;6182:164;;;-1:-1:-1;6297:1:90;;-1:-1:-1;6301:30:90;;-1:-1:-1;6333:1:90;6281:54;;6182:164;6457:24;;;6440:14;6457:24;;;;;;;;;63746:25:97;;;63819:4;63807:17;;63787:18;;;63780:45;;;;63841:18;;;63834:34;;;63884:18;;;63877:34;;;6457:24:90;;63718:19:97;;6457:24:90;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6457:24:90;;-1:-1:-1;;6457:24:90;;;-1:-1:-1;;;;;;;6495:20:90;;6491:113;;-1:-1:-1;6547:1:90;;-1:-1:-1;6551:29:90;;-1:-1:-1;6547:1:90;;-1:-1:-1;6531:62:90;;6491:113;6622:6;-1:-1:-1;6630:20:90;;-1:-1:-1;6630:20:90;;-1:-1:-1;5140:1530:90;;;;;;;;;:::o;9229:147:91:-;9292:7;9322:1;9318;:5;:51;;9564:13;9655:15;;;9690:4;9683:15;;;9736:4;9720:21;;9318:51;;;9564:13;9655:15;;;9690:4;9683:15;;;9736:4;9720:21;;9326:20;9496:261;14:367:97;77:8;87:6;141:3;134:4;126:6;122:17;118:27;108:55;;159:1;156;149:12;108:55;-1:-1:-1;182:20:97;;225:18;214:30;;211:50;;;257:1;254;247:12;211:50;294:4;286:6;282:17;270:29;;354:3;347:4;337:6;334:1;330:14;322:6;318:27;314:38;311:47;308:67;;;371:1;368;361:12;308:67;14:367;;;;;:::o;386:437::-;472:6;480;533:2;521:9;512:7;508:23;504:32;501:52;;;549:1;546;539:12;501:52;589:9;576:23;622:18;614:6;611:30;608:50;;;654:1;651;644:12;608:50;693:70;755:7;746:6;735:9;731:22;693:70;:::i;:::-;782:8;;667:96;;-1:-1:-1;386:437:97;-1:-1:-1;;;;386:437:97:o;1010:226::-;1069:6;1122:2;1110:9;1101:7;1097:23;1093:32;1090:52;;;1138:1;1135;1128:12;1090:52;-1:-1:-1;1183:23:97;;1010:226;-1:-1:-1;1010:226:97:o;1241:154::-;-1:-1:-1;;;;;1320:5:97;1316:54;1309:5;1306:65;1296:93;;1385:1;1382;1375:12;1296:93;1241:154;:::o;1400:247::-;1459:6;1512:2;1500:9;1491:7;1487:23;1483:32;1480:52;;;1528:1;1525;1518:12;1480:52;1567:9;1554:23;1586:31;1611:5;1586:31;:::i;1652:551::-;1747:6;1755;1763;1816:2;1804:9;1795:7;1791:23;1787:32;1784:52;;;1832:1;1829;1822:12;1784:52;1877:23;;;-1:-1:-1;1975:2:97;1960:18;;1947:32;2002:18;1991:30;;1988:50;;;2034:1;2031;2024:12;1988:50;2073:70;2135:7;2126:6;2115:9;2111:22;2073:70;:::i;:::-;1652:551;;2162:8;;-1:-1:-1;2047:96:97;;-1:-1:-1;;;;1652:551:97:o;2208:347::-;2259:8;2269:6;2323:3;2316:4;2308:6;2304:17;2300:27;2290:55;;2341:1;2338;2331:12;2290:55;-1:-1:-1;2364:20:97;;2407:18;2396:30;;2393:50;;;2439:1;2436;2429:12;2393:50;2476:4;2468:6;2464:17;2452:29;;2528:3;2521:4;2512:6;2504;2500:19;2496:30;2493:39;2490:59;;;2545:1;2542;2535:12;2560:1089;2677:6;2685;2693;2701;2709;2717;2725;2778:3;2766:9;2757:7;2753:23;2749:33;2746:53;;;2795:1;2792;2785:12;2746:53;2834:9;2821:23;2853:31;2878:5;2853:31;:::i;:::-;2903:5;-1:-1:-1;2981:2:97;2966:18;;2953:32;;-1:-1:-1;3084:2:97;3069:18;;3056:32;;-1:-1:-1;3165:2:97;3150:18;;3137:32;3192:18;3181:30;;3178:50;;;3224:1;3221;3214:12;3178:50;3263:58;3313:7;3304:6;3293:9;3289:22;3263:58;:::i;:::-;3340:8;;-1:-1:-1;3237:84:97;-1:-1:-1;;3428:3:97;3413:19;;3400:33;3458:18;3445:32;;3442:52;;;3490:1;3487;3480:12;3442:52;3529:60;3581:7;3570:8;3559:9;3555:24;3529:60;:::i;:::-;2560:1089;;;;-1:-1:-1;2560:1089:97;;-1:-1:-1;2560:1089:97;;;;3503:86;;-1:-1:-1;;;2560:1089:97:o;3654:142::-;3730:20;;3759:31;3730:20;3759:31;:::i;:::-;3654:142;;;:::o;3801:1627::-;3991:6;3999;4007;4015;4023;4031;4039;4047;4055;4063;4071:7;4125:3;4113:9;4104:7;4100:23;4096:33;4093:53;;;4142:1;4139;4132:12;4093:53;4182:9;4169:23;4215:18;4207:6;4204:30;4201:50;;;4247:1;4244;4237:12;4201:50;4286:70;4348:7;4339:6;4328:9;4324:22;4286:70;:::i;:::-;4375:8;;-1:-1:-1;4260:96:97;-1:-1:-1;;4479:2:97;4464:18;;4451:32;;-1:-1:-1;4580:2:97;4565:18;;4552:32;;-1:-1:-1;4629:46:97;4671:2;4656:18;;4629:46;:::i;:::-;4619:56;;4728:3;4717:9;4713:19;4700:33;4758:18;4748:8;4745:32;4742:52;;;4790:1;4787;4780:12;4742:52;4829:60;4881:7;4870:8;4859:9;4855:24;4829:60;:::i;:::-;4908:8;;-1:-1:-1;4803:86:97;-1:-1:-1;;5016:3:97;5001:19;;4988:33;;-1:-1:-1;5120:3:97;5105:19;;5092:33;;-1:-1:-1;5204:3:97;5189:19;;5176:33;5234:18;5221:32;;5218:52;;;5266:1;5263;5256:12;5218:52;5306:60;5358:7;5347:8;5336:9;5332:24;5306:60;:::i;:::-;5279:87;;5385:8;5375:18;;;5413:9;5402:20;;;3801:1627;;;;;;;;;;;;;;:::o;5433:250::-;5518:1;5528:113;5542:6;5539:1;5536:13;5528:113;;;5618:11;;;5612:18;5599:11;;;5592:39;5564:2;5557:10;5528:113;;;-1:-1:-1;;5675:1:97;5657:16;;5650:27;5433:250::o;5688:270::-;5729:3;5767:5;5761:12;5794:6;5789:3;5782:19;5810:76;5879:6;5872:4;5867:3;5863:14;5856:4;5849:5;5845:16;5810:76;:::i;:::-;5940:2;5919:15;-1:-1:-1;;5915:29:97;5906:39;;;;5947:4;5902:50;;5688:270;-1:-1:-1;;5688:270:97:o;5963:577::-;6014:3;6045;6077:5;6071:12;6104:6;6099:3;6092:19;6136:4;6131:3;6127:14;6120:21;;6194:4;6184:6;6181:1;6177:14;6170:5;6166:26;6162:37;6233:4;6226:5;6222:16;6256:1;6266:248;6280:6;6277:1;6274:13;6266:248;;;6367:2;6363:7;6355:5;6349:4;6345:16;6341:30;6336:3;6329:43;6393:37;6425:4;6416:6;6410:13;6393:37;:::i;:::-;6465:4;6490:14;;;;6385:45;;-1:-1:-1;6453:17:97;;;;;6302:1;6295:9;6266:248;;;-1:-1:-1;6530:4:97;;5963:577;-1:-1:-1;;;;;;5963:577:97:o;6545:348::-;6770:2;6759:9;6752:21;6733:4;6790:54;6840:2;6829:9;6825:18;6817:6;6790:54;:::i;:::-;6782:62;;6880:6;6875:2;6864:9;6860:18;6853:34;6545:348;;;;;:::o;6898:848::-;6998:6;7006;7014;7022;7030;7083:2;7071:9;7062:7;7058:23;7054:32;7051:52;;;7099:1;7096;7089:12;7051:52;7138:9;7125:23;7157:31;7182:5;7157:31;:::i;:::-;7207:5;-1:-1:-1;7263:2:97;7248:18;;7235:32;7290:18;7279:30;;7276:50;;;7322:1;7319;7312:12;7276:50;7361:58;7411:7;7402:6;7391:9;7387:22;7361:58;:::i;:::-;7438:8;;-1:-1:-1;7335:84:97;-1:-1:-1;;7526:2:97;7511:18;;7498:32;7555:18;7542:32;;7539:52;;;7587:1;7584;7577:12;7539:52;7626:60;7678:7;7667:8;7656:9;7652:24;7626:60;:::i;:::-;6898:848;;;;-1:-1:-1;6898:848:97;;-1:-1:-1;7705:8:97;;7600:86;6898:848;-1:-1:-1;;;6898:848:97:o;8617:433::-;8667:3;8705:5;8699:12;8732:6;8727:3;8720:19;8764:4;8759:3;8755:14;8748:21;;8803:4;8796:5;8792:16;8826:1;8836:189;8850:6;8847:1;8844:13;8836:189;;;8925:13;;8918:21;8911:29;8899:42;;8970:4;8961:14;;;;8998:17;;;;8872:1;8865:9;8836:189;;;-1:-1:-1;9041:3:97;;8617:433;-1:-1:-1;;;;8617:433:97:o;9055:472::-;9324:2;9313:9;9306:21;9287:4;9350:53;9399:2;9388:9;9384:18;9376:6;9350:53;:::i;:::-;9451:9;9443:6;9439:22;9434:2;9423:9;9419:18;9412:50;9479:42;9514:6;9506;9479:42;:::i;9724:409::-;9794:6;9802;9855:2;9843:9;9834:7;9830:23;9826:32;9823:52;;;9871:1;9868;9861:12;9823:52;9911:9;9898:23;9944:18;9936:6;9933:30;9930:50;;;9976:1;9973;9966:12;9930:50;10015:58;10065:7;10056:6;10045:9;10041:22;10015:58;:::i;10138:217::-;10285:2;10274:9;10267:21;10248:4;10305:44;10345:2;10334:9;10330:18;10322:6;10305:44;:::i;10836:803::-;10960:6;10968;10976;10984;10992;11045:3;11033:9;11024:7;11020:23;11016:33;11013:53;;;11062:1;11059;11052:12;11013:53;11107:23;;;-1:-1:-1;11227:2:97;11212:18;;11199:32;;-1:-1:-1;11330:2:97;11315:18;;11302:32;;-1:-1:-1;11411:2:97;11396:18;;11383:32;11438:18;11427:30;;11424:50;;;11470:1;11467;11460:12;11424:50;11509:70;11571:7;11562:6;11551:9;11547:22;11509:70;:::i;11644:543::-;11941:2;11930:9;11923:21;11904:4;11967:53;12016:2;12005:9;12001:18;11993:6;11967:53;:::i;:::-;12068:9;12060:6;12056:22;12051:2;12040:9;12036:18;12029:50;12096:42;12131:6;12123;12096:42;:::i;:::-;12088:50;;;12174:6;12169:2;12158:9;12154:18;12147:34;11644:543;;;;;;:::o;12192:277::-;12389:2;12378:9;12371:21;12352:4;12409:54;12459:2;12448:9;12444:18;12436:6;12409:54;:::i;12474:1339::-;12617:6;12625;12633;12641;12649;12657;12665;12673;12681;12734:3;12722:9;12713:7;12709:23;12705:33;12702:53;;;12751:1;12748;12741:12;12702:53;12796:23;;;-1:-1:-1;12916:2:97;12901:18;;12888:32;;-1:-1:-1;12998:2:97;12983:18;;12970:32;13011:33;12970:32;13011:33;:::i;:::-;13063:7;-1:-1:-1;13121:2:97;13106:18;;13093:32;13148:18;13137:30;;13134:50;;;13180:1;13177;13170:12;13134:50;13219:58;13269:7;13260:6;13249:9;13245:22;13219:58;:::i;:::-;13296:8;;-1:-1:-1;13193:84:97;-1:-1:-1;;13404:3:97;13389:19;;13376:33;;-1:-1:-1;13508:3:97;13493:19;;13480:33;;-1:-1:-1;13592:3:97;13577:19;;13564:33;13622:18;13609:32;;13606:52;;;13654:1;13651;13644:12;13606:52;13693:60;13745:7;13734:8;13723:9;13719:24;13693:60;:::i;:::-;13667:86;;13772:8;13762:18;;;13799:8;13789:18;;;12474:1339;;;;;;;;;;;:::o;13818:764::-;13915:6;13923;13931;13939;13947;14000:3;13988:9;13979:7;13975:23;13971:33;13968:53;;;14017:1;14014;14007:12;13968:53;14062:23;;;-1:-1:-1;14160:2:97;14145:18;;14132:32;14187:18;14176:30;;14173:50;;;14219:1;14216;14209:12;14173:50;14258:58;14308:7;14299:6;14288:9;14284:22;14258:58;:::i;:::-;13818:764;;14335:8;;-1:-1:-1;14232:84:97;;14443:2;14428:18;;14415:32;;14546:2;14531:18;;;14518:32;;-1:-1:-1;13818:764:97;-1:-1:-1;;;;13818:764:97:o;14587:643::-;14675:6;14683;14691;14699;14752:2;14740:9;14731:7;14727:23;14723:32;14720:52;;;14768:1;14765;14758:12;14720:52;14813:23;;;-1:-1:-1;14933:2:97;14918:18;;14905:32;;-1:-1:-1;15014:2:97;14999:18;;14986:32;15041:18;15030:30;;15027:50;;;15073:1;15070;15063:12;15027:50;15112:58;15162:7;15153:6;15142:9;15138:22;15112:58;:::i;:::-;14587:643;;;;-1:-1:-1;15189:8:97;-1:-1:-1;;;;14587:643:97:o;15235:435::-;15287:3;15325:5;15319:12;15352:6;15347:3;15340:19;15384:4;15379:3;15375:14;15368:21;;15423:4;15416:5;15412:16;15446:1;15456:189;15470:6;15467:1;15464:13;15456:189;;;15546:13;;15542:2;15531:29;15519:42;;15590:4;15581:14;;;;15618:17;;;;15492:1;15485:9;15456:189;;15675:436;15727:3;15765:5;15759:12;15792:6;15787:3;15780:19;15824:4;15819:3;15815:14;15808:21;;15863:4;15856:5;15852:16;15886:1;15896:190;15910:6;15907:1;15904:13;15896:190;;;15975:13;;15990:10;15971:30;15959:43;;16031:4;16022:14;;;;16059:17;;;;15932:1;15925:9;15896:190;;16116:1804;16717:3;16706:9;16699:22;16680:4;16744:45;16784:3;16773:9;16769:19;16761:6;16744:45;:::i;:::-;16840:6;16836:2;16825:22;16820:2;16809:9;16805:18;16798:50;16896:10;16888:6;16884:23;16879:2;16868:9;16864:18;16857:51;16956:9;16948:6;16944:22;16939:2;16928:9;16924:18;16917:50;16990:43;17026:6;17018;16990:43;:::i;:::-;16976:57;;17082:9;17074:6;17070:22;17064:3;17053:9;17049:19;17042:51;17116:43;17152:6;17144;17116:43;:::i;:::-;17102:57;;17208:9;17200:6;17196:22;17190:3;17179:9;17175:19;17168:51;17242:42;17277:6;17269;17242:42;:::i;:::-;17228:56;;17333:9;17325:6;17321:22;17315:3;17304:9;17300:19;17293:51;17367:43;17403:6;17395;17367:43;:::i;:::-;17447:22;;;17441:3;17426:19;;17419:51;17519:13;;17541:22;;;17591:2;17617:15;;;;-1:-1:-1;17579:15:97;;;;17650:1;17660:234;17674:6;17671:1;17668:13;17660:234;;;17739:13;;-1:-1:-1;;;;;17735:78:97;17723:91;;17843:2;17869:15;;;;17834:12;;;;17696:1;17689:9;17660:234;;;-1:-1:-1;17911:3:97;;16116:1804;-1:-1:-1;;;;;;;;;;;;16116:1804:97:o;18178:346::-;18246:6;18254;18307:2;18295:9;18286:7;18282:23;18278:32;18275:52;;;18323:1;18320;18313:12;18275:52;-1:-1:-1;;18368:23:97;;;18488:2;18473:18;;;18460:32;;-1:-1:-1;18178:346:97:o;18529:793::-;18880:3;18869:9;18862:22;18843:4;18907:45;18947:3;18936:9;18932:19;18924:6;18907:45;:::i;:::-;19003:6;18999:2;18988:22;18983:2;18972:9;18968:18;18961:50;19059:10;19051:6;19047:23;19042:2;19031:9;19027:18;19020:51;19119:9;19111:6;19107:22;19102:2;19091:9;19087:18;19080:50;19153:43;19189:6;19181;19153:43;:::i;:::-;19139:57;;19245:9;19237:6;19233:22;19227:3;19216:9;19212:19;19205:51;19273:43;19309:6;19301;19273:43;:::i;19327:785::-;19424:6;19432;19440;19448;19456;19509:3;19497:9;19488:7;19484:23;19480:33;19477:53;;;19526:1;19523;19516:12;19477:53;19571:23;;;-1:-1:-1;19691:2:97;19676:18;;19663:32;;-1:-1:-1;19773:2:97;19758:18;;19745:32;19786:33;19745:32;19786:33;:::i;:::-;19838:7;-1:-1:-1;19896:2:97;19881:18;;19868:32;19923:18;19912:30;;19909:50;;;19955:1;19952;19945:12;20117:490;20306:2;20295:9;20288:21;20345:6;20340:2;20329:9;20325:18;20318:34;20269:4;20375:66;20367:6;20364:78;20361:98;;;20455:1;20452;20445:12;20361:98;20489:6;20486:1;20482:14;20546:6;20538;20533:2;20522:9;20518:18;20505:48;20574:22;;;;20598:2;20570:31;;20117:490;-1:-1:-1;;;20117:490:97:o;20612:230::-;20682:6;20735:2;20723:9;20714:7;20710:23;20706:32;20703:52;;;20751:1;20748;20741:12;20703:52;-1:-1:-1;20796:16:97;;20612:230;-1:-1:-1;20612:230:97:o;22276:251::-;22346:6;22399:2;22387:9;22378:7;22374:23;22370:32;22367:52;;;22415:1;22412;22405:12;22367:52;22447:9;22441:16;22466:31;22491:5;22466:31;:::i;23573:184::-;-1:-1:-1;;;23622:1:97;23615:88;23722:4;23719:1;23712:15;23746:4;23743:1;23736:15;24116:184;-1:-1:-1;;;24165:1:97;24158:88;24265:4;24262:1;24255:15;24289:4;24286:1;24279:15;24305:128;24372:9;;;24393:11;;;24390:37;;;24407:18;;:::i;24797:620::-;24968:3;24999;25046:6;24968:3;25080:310;25094:6;25091:1;25088:13;25080:310;;;25169:6;25156:20;25189:31;25214:5;25189:31;:::i;:::-;-1:-1:-1;;;;;25247:54:97;25233:69;;25335:4;25324:16;;;;25363:17;;;;;25116:1;25109:9;25080:310;;;-1:-1:-1;25406:5:97;;24797:620;-1:-1:-1;;;;;24797:620:97:o;25422:707::-;25622:2;25634:21;;;25607:18;;25690:22;;;25574:4;25769:6;25743:2;25728:18;;25574:4;25803:300;25817:6;25814:1;25811:13;25803:300;;;25892:6;25879:20;25912:31;25937:5;25912:31;:::i;:::-;-1:-1:-1;;;;;25968:54:97;25956:67;;26052:2;26078:15;;;;26043:12;;;;25839:1;25832:9;25803:300;;;-1:-1:-1;26120:3:97;25422:707;-1:-1:-1;;;;;25422:707:97:o;26134:266::-;26222:6;26217:3;26210:19;26274:6;26267:5;26260:4;26255:3;26251:14;26238:43;-1:-1:-1;26326:1:97;26301:16;;;26319:4;26297:27;;;26290:38;;;;26382:2;26361:15;;;-1:-1:-1;;26357:29:97;26348:39;;;26344:50;;26134:266::o;26405:696::-;-1:-1:-1;;;;;26706:6:97;26702:55;26691:9;26684:74;26794:6;26789:2;26778:9;26774:18;26767:34;26837:6;26832:2;26821:9;26817:18;26810:34;26880:3;26875:2;26864:9;26860:18;26853:31;26665:4;26907:62;26964:3;26953:9;26949:19;26941:6;26933;26907:62;:::i;:::-;27018:9;27010:6;27006:22;27000:3;26989:9;26985:19;26978:51;27046:49;27088:6;27080;27072;27046:49;:::i;:::-;27038:57;26405:696;-1:-1:-1;;;;;;;;;;26405:696:97:o;27106:1226::-;27326:2;27338:21;;;27311:18;;27394:22;;;-1:-1:-1;27447:2:97;27496:1;27492:14;;;27477:30;;27473:39;;;27432:18;;27535:6;-1:-1:-1;;;27587:14:97;27583:27;;;27579:41;27629:674;27643:6;27640:1;27637:13;27629:674;;;27708:22;;;-1:-1:-1;;27704:36:97;27692:49;;27780:20;;27823:27;;;27813:55;;27864:1;27861;27854:12;27813:55;27894:31;;28010:2;27999:14;;;27952:19;28040:18;28029:30;;28026:50;;;28072:1;28069;28062:12;28026:50;28125:6;28109:14;28105:27;28096:7;28092:41;28089:61;;;28146:1;28143;28136:12;28089:61;28173:50;28216:6;28208;28199:7;28173:50;:::i;:::-;28163:60;;;;28258:2;28250:6;28246:15;28236:25;;28290:2;28285:3;28281:12;28274:19;;27665:1;27662;27658:9;27653:14;;27629:674;;;-1:-1:-1;28320:6:97;;27106:1226;-1:-1:-1;;;;;;;27106:1226:97:o;28337:184::-;-1:-1:-1;;;28386:1:97;28379:88;28486:4;28483:1;28476:15;28510:4;28507:1;28500:15;28526:275;28597:2;28591:9;28662:2;28643:13;;-1:-1:-1;;28639:27:97;28627:40;;28697:18;28682:34;;28718:22;;;28679:62;28676:88;;;28744:18;;:::i;:::-;28780:2;28773:22;28526:275;;-1:-1:-1;28526:275:97:o;28806:181::-;28864:4;28897:18;28889:6;28886:30;28883:56;;;28919:18;;:::i;:::-;-1:-1:-1;28964:1:97;28960:14;28976:4;28956:25;;28806:181::o;28992:186::-;29040:4;29073:18;29065:6;29062:30;29059:56;;;29095:18;;:::i;:::-;-1:-1:-1;29161:2:97;29140:15;-1:-1:-1;;29136:29:97;29167:4;29132:40;;28992:186::o;29183:320::-;29258:5;29287:52;29303:35;29331:6;29303:35;:::i;:::-;29287:52;:::i;:::-;29278:61;;29362:6;29355:5;29348:21;29402:3;29393:6;29388:3;29384:16;29381:25;29378:45;;;29419:1;29416;29409:12;29378:45;29432:65;29490:6;29483:4;29476:5;29472:16;29467:3;29432:65;:::i;29508:235::-;29561:5;29614:3;29607:4;29599:6;29595:17;29591:27;29581:55;;29632:1;29629;29622:12;29581:55;29654:83;29733:3;29724:6;29718:13;29711:4;29703:6;29699:17;29654:83;:::i;29748:831::-;29811:5;29864:3;29857:4;29849:6;29845:17;29841:27;29831:55;;29882:1;29879;29872:12;29831:55;29915:6;29909:13;29942:62;29958:45;29996:6;29958:45;:::i;29942:62::-;30028:3;30052:6;30047:3;30040:19;30084:4;30079:3;30075:14;30068:21;;30145:4;30135:6;30132:1;30128:14;30120:6;30116:27;30112:38;30098:52;;30173:3;30165:6;30162:15;30159:35;;;30190:1;30187;30180:12;30159:35;30226:4;30218:6;30214:17;30240:308;30256:6;30251:3;30248:15;30240:308;;;30337:3;30331:10;30373:18;30360:11;30357:35;30354:55;;;30405:1;30402;30395:12;30354:55;30434:69;30499:3;30492:4;30478:11;30470:6;30466:24;30462:35;30434:69;:::i;:::-;30422:82;;-1:-1:-1;30533:4:97;30524:14;;;;30273;30240:308;;30584:370;30688:6;30741:2;30729:9;30720:7;30716:23;30712:32;30709:52;;;30757:1;30754;30747:12;30709:52;30790:9;30784:16;30823:18;30815:6;30812:30;30809:50;;;30855:1;30852;30845:12;30809:50;30878:70;30940:7;30931:6;30920:9;30916:22;30878:70;:::i;30959:458::-;31039:6;31092:2;31080:9;31071:7;31067:23;31063:32;31060:52;;;31108:1;31105;31098:12;31060:52;31141:9;31135:16;31174:18;31166:6;31163:30;31160:50;;;31206:1;31203;31196:12;31160:50;31229:22;;31282:4;31274:13;;31270:27;-1:-1:-1;31260:55:97;;31311:1;31308;31301:12;31260:55;31334:77;31403:7;31398:2;31392:9;31387:2;31383;31379:11;31334:77;:::i;31422:289::-;31553:3;31591:6;31585:13;31607:66;31666:6;31661:3;31654:4;31646:6;31642:17;31607:66;:::i;:::-;31689:16;;;;;31422:289;-1:-1:-1;;31422:289:97:o;31716:273::-;31901:6;31893;31888:3;31875:33;31857:3;31927:16;;31952:13;;;31927:16;31716:273;-1:-1:-1;31716:273:97:o;32353:366::-;-1:-1:-1;;;;;32544:6:97;32540:55;32529:9;32522:74;32632:2;32627;32616:9;32612:18;32605:30;32503:4;32652:61;32709:2;32698:9;32694:18;32686:6;32678;32652:61;:::i;33326:521::-;33403:4;33409:6;33469:11;33456:25;33563:2;33559:7;33548:8;33532:14;33528:29;33524:43;33504:18;33500:68;33490:96;;33582:1;33579;33572:12;33490:96;33609:33;;33661:20;;;-1:-1:-1;33704:18:97;33693:30;;33690:50;;;33736:1;33733;33726:12;33690:50;33769:4;33757:17;;-1:-1:-1;33800:14:97;33796:27;;;33786:38;;33783:58;;;33837:1;33834;33827:12;34411:244;34568:2;34557:9;34550:21;34531:4;34588:61;34645:2;34634:9;34630:18;34622:6;34614;34588:61;:::i;34660:170::-;34757:10;34750:18;;;34730;;;34726:43;;34781:20;;34778:46;;;34804:18;;:::i;34835:415::-;34875:7;-1:-1:-1;;;;;34912:1:97;34908:66;-1:-1:-1;;;;;34998:1:97;34994:66;-1:-1:-1;;;;;35093:3:97;35088;35084:13;35080:78;35069:89;;35214:3;35205:7;35201:17;35196:3;35193:26;35187:3;35180:11;35177:43;35167:77;;35224:18;;:::i;35255:184::-;-1:-1:-1;;;35304:1:97;35297:88;35404:4;35401:1;35394:15;35428:4;35425:1;35418:15;35444:275;35484:1;-1:-1:-1;;;;;35515:1:97;35511:66;35596:3;35586:37;;35603:18;;:::i;:::-;35709:3;-1:-1:-1;;;;;35645:1:97;35641:66;35637:76;35632:81;;;35444:275;;;;:::o;35724:125::-;35789:9;;;35810:10;;;35807:36;;;35823:18;;:::i;36212:437::-;36291:1;36287:12;;;;36334;;;36355:61;;36409:4;36401:6;36397:17;36387:27;;36355:61;36462:2;36454:6;36451:14;36431:18;36428:38;36425:218;;-1:-1:-1;;;36496:1:97;36489:88;36600:4;36597:1;36590:15;36628:4;36625:1;36618:15;36425:218;;36212:437;;;:::o;38373:486::-;38415:5;38468:3;38461:4;38453:6;38449:17;38445:27;38435:55;;38486:1;38483;38476:12;38435:55;38526:6;38513:20;38557:52;38573:35;38601:6;38573:35;:::i;38557:52::-;38634:6;38625:7;38618:23;38688:3;38681:4;38672:6;38664;38660:19;38656:30;38653:39;38650:59;;;38705:1;38702;38695:12;38650:59;38770:6;38763:4;38755:6;38751:17;38744:4;38735:7;38731:18;38718:59;38826:1;38797:20;;;38819:4;38793:31;38786:42;;;;38801:7;38373:486;-1:-1:-1;;;38373:486:97:o;38864:648::-;38959:6;38967;38975;39028:2;39016:9;39007:7;39003:23;38999:32;38996:52;;;39044:1;39041;39034:12;38996:52;39089:23;;;-1:-1:-1;39187:2:97;39172:18;;39159:32;39214:18;39203:30;;39200:50;;;39246:1;39243;39236:12;39200:50;39269:49;39310:7;39301:6;39290:9;39286:22;39269:49;:::i;:::-;39259:59;;;39371:2;39360:9;39356:18;39343:32;39400:18;39390:8;39387:32;39384:52;;;39432:1;39429;39422:12;39384:52;39455:51;39498:7;39487:8;39476:9;39472:24;39455:51;:::i;:::-;39445:61;;;38864:648;;;;;:::o;40579:575::-;40797:13;;40740:3;;40771;;40866:4;40854:17;;40740:3;40899:228;40913:6;40910:1;40907:13;40899:228;;;40980:13;;-1:-1:-1;;;;;40976:62:97;40962:77;;41072:4;41061:16;;;;41100:17;;;;40935:1;40928:9;40899:228;;;-1:-1:-1;41143:5:97;;40579:575;-1:-1:-1;;;;;40579:575:97:o;41506:164::-;41582:13;;41631;;41624:21;41614:32;;41604:60;;41660:1;41657;41650:12;41675:1157;41810:6;41818;41871:2;41859:9;41850:7;41846:23;41842:32;41839:52;;;41887:1;41884;41877:12;41839:52;41920:9;41914:16;41953:18;41945:6;41942:30;41939:50;;;41985:1;41982;41975:12;41939:50;42008:22;;42061:4;42053:13;;42049:27;-1:-1:-1;42039:55:97;;42090:1;42087;42080:12;42039:55;42123:2;42117:9;42146:62;42162:45;42200:6;42162:45;:::i;42146:62::-;42230:3;42254:6;42249:3;42242:19;42286:4;42281:3;42277:14;42270:21;;42343:4;42333:6;42330:1;42326:14;42322:2;42318:23;42314:34;42300:48;;42371:7;42363:6;42360:19;42357:39;;;42392:1;42389;42382:12;42357:39;42424:4;42420:2;42416:13;42405:24;;42438:160;42454:6;42449:3;42446:15;42438:160;;;42522:31;42549:3;42522:31;:::i;:::-;42510:44;;42583:4;42471:14;;;;42574;;;;42438:160;;;42617:5;42607:15;;;;;;42668:4;42657:9;42653:20;42647:27;42699:18;42689:8;42686:32;42683:52;;;42731:1;42728;42721:12;42683:52;42754:72;42818:7;42807:8;42796:9;42792:24;42754:72;:::i;:::-;42744:82;;;41675:1157;;;;;:::o;44244:660::-;44549:6;44538:9;44531:25;-1:-1:-1;;;;;44596:6:97;44592:55;44587:2;44576:9;44572:18;44565:83;44684:3;44679:2;44668:9;44664:18;44657:31;44512:4;44705:62;44762:3;44751:9;44747:19;44739:6;44731;44705:62;:::i;:::-;44798:2;44783:18;;44776:34;;;;-1:-1:-1;44841:3:97;44826:19;;44819:35;;;;44885:3;44870:19;;;44863:35;44697:70;44244:660;-1:-1:-1;;;;44244:660:97:o;45830:168::-;45903:9;;;45934;;45951:15;;;45945:22;;45931:37;45921:71;;45972:18;;:::i;46003:120::-;46043:1;46069;46059:35;;46074:18;;:::i;:::-;-1:-1:-1;46108:9:97;;46003:120::o;46128:386::-;46341:6;46330:9;46323:25;46384:6;46379:2;46368:9;46364:18;46357:34;46427:2;46422;46411:9;46407:18;46400:30;46304:4;46447:61;46504:2;46493:9;46489:18;46481:6;46473;46447:61;:::i;:::-;46439:69;46128:386;-1:-1:-1;;;;;;46128:386:97:o;46706:135::-;46745:3;46766:17;;;46763:43;;46786:18;;:::i;:::-;-1:-1:-1;46833:1:97;46822:13;;46706:135::o;47128:335::-;47207:6;47260:2;47248:9;47239:7;47235:23;47231:32;47228:52;;;47276:1;47273;47266:12;47228:52;47309:9;47303:16;47342:18;47334:6;47331:30;47328:50;;;47374:1;47371;47364:12;47328:50;47397:60;47449:7;47440:6;47429:9;47425:22;47397:60;:::i;47468:120::-;47557:5;47553:2;47542:21;47535:5;47532:32;47522:60;;47578:1;47575;47568:12;47593:414;47670:6;47678;47731:2;47719:9;47710:7;47706:23;47702:32;47699:52;;;47747:1;47744;47737:12;47699:52;47779:9;47773:16;47798:30;47822:5;47798:30;:::i;:::-;47897:2;47882:18;;47876:25;47847:5;;-1:-1:-1;47945:10:97;47932:24;;47920:37;;47910:65;;47971:1;47968;47961:12;47910:65;47994:7;47984:17;;;47593:414;;;;;:::o;48012:372::-;48099:6;48107;48160:2;48148:9;48139:7;48135:23;48131:32;48128:52;;;48176:1;48173;48166:12;48128:52;48208:9;48202:16;48227:31;48252:5;48227:31;:::i;:::-;48348:2;48333:18;;;;48327:25;48277:5;;48327:25;;-1:-1:-1;;;48012:372:97:o;48389:718::-;48454:5;48507:3;48500:4;48492:6;48488:17;48484:27;48474:55;;48525:1;48522;48515:12;48474:55;48558:6;48552:13;48585:62;48601:45;48639:6;48601:45;:::i;48585:62::-;48671:3;48695:6;48690:3;48683:19;48727:4;48722:3;48718:14;48711:21;;48788:4;48778:6;48775:1;48771:14;48763:6;48759:27;48755:38;48741:52;;48816:3;48808:6;48805:15;48802:35;;;48833:1;48830;48823:12;48802:35;48869:4;48861:6;48857:17;48883:193;48899:6;48894:3;48891:15;48883:193;;;48991:10;;49014:18;;49061:4;49052:14;;;;48916;48883:193;;49112:1207;49241:6;49249;49302:2;49290:9;49281:7;49277:23;49273:32;49270:52;;;49318:1;49315;49308:12;49270:52;49351:9;49345:16;49384:18;49376:6;49373:30;49370:50;;;49416:1;49413;49406:12;49370:50;49439:22;;49492:4;49484:13;;49480:27;-1:-1:-1;49470:55:97;;49521:1;49518;49511:12;49470:55;49554:2;49548:9;49577:62;49593:45;49631:6;49593:45;:::i;49577:62::-;49661:3;49685:6;49680:3;49673:19;49717:4;49712:3;49708:14;49701:21;;49774:4;49764:6;49761:1;49757:14;49753:2;49749:23;49745:34;49731:48;;49802:7;49794:6;49791:19;49788:39;;;49823:1;49820;49813:12;49788:39;49855:4;49851:2;49847:13;49836:24;;49869:214;49885:6;49880:3;49877:15;49869:214;;;49960:3;49954:10;49977:31;50002:5;49977:31;:::i;:::-;50021:18;;50068:4;49902:14;;;;50059;;;;49869:214;;;50102:5;50092:15;;;;;;50153:4;50142:9;50138:20;50132:27;50184:18;50174:8;50171:32;50168:52;;;50216:1;50213;50206:12;50168:52;50239:74;50305:7;50294:8;50283:9;50279:24;50239:74;:::i;51651:288::-;51826:6;51815:9;51808:25;51869:2;51864;51853:9;51849:18;51842:30;51789:4;51889:44;51929:2;51918:9;51914:18;51906:6;51889:44;:::i;51944:721::-;51998:5;52051:3;52044:4;52036:6;52032:17;52028:27;52018:55;;52069:1;52066;52059:12;52018:55;52109:6;52096:20;52136:62;52152:45;52190:6;52152:45;:::i;52136:62::-;52222:3;52246:6;52241:3;52234:19;52278:4;52273:3;52269:14;52262:21;;52339:4;52329:6;52326:1;52322:14;52314:6;52310:27;52306:38;52292:52;;52367:3;52359:6;52356:15;52353:35;;;52384:1;52381;52374:12;52353:35;52420:4;52412:6;52408:17;52434:200;52450:6;52445:3;52442:15;52434:200;;;52542:17;;52572:18;;52619:4;52610:14;;;;52467;52434:200;;52670:462;52763:6;52771;52824:2;52812:9;52803:7;52799:23;52795:32;52792:52;;;52840:1;52837;52830:12;52792:52;52885:23;;;-1:-1:-1;52983:2:97;52968:18;;52955:32;53010:18;52999:30;;52996:50;;;53042:1;53039;53032:12;52996:50;53065:61;53118:7;53109:6;53098:9;53094:22;53065:61;:::i;55115:825::-;55251:6;55259;55267;55275;55328:3;55316:9;55307:7;55303:23;55299:33;55296:53;;;55345:1;55342;55335:12;55296:53;55390:23;;;-1:-1:-1;55488:2:97;55473:18;;55460:32;55515:18;55504:30;;55501:50;;;55547:1;55544;55537:12;55501:50;55570:61;55623:7;55614:6;55603:9;55599:22;55570:61;:::i;:::-;55560:71;-1:-1:-1;;55704:2:97;55689:18;;55676:32;;-1:-1:-1;55787:2:97;55772:18;;55759:32;55816:18;55803:32;;55800:52;;;55848:1;55845;55838:12;55800:52;55871:63;55926:7;55915:8;55904:9;55900:24;55871:63;:::i;:::-;55861:73;;;55115:825;;;;;;;:::o;56318:531::-;56587:6;56576:9;56569:25;56630:6;56625:2;56614:9;56610:18;56603:34;56673:3;56668:2;56657:9;56653:18;56646:31;56550:4;56694:62;56751:3;56740:9;56736:19;56728:6;56720;56694:62;:::i;:::-;56787:2;56772:18;;56765:34;;;;-1:-1:-1;56830:3:97;56815:19;56808:35;56686:70;56318:531;-1:-1:-1;;;;56318:531:97:o;56979:517::-;57080:2;57075:3;57072:11;57069:421;;;57116:5;57113:1;57106:16;57160:4;57157:1;57147:18;57230:2;57218:10;57214:19;57211:1;57207:27;57201:4;57197:38;57266:4;57254:10;57251:20;57248:47;;;-1:-1:-1;57289:4:97;57248:47;57344:2;57339:3;57335:12;57332:1;57328:20;57322:4;57318:31;57308:41;;57399:81;57417:2;57410:5;57407:13;57399:81;;;57476:1;57462:16;;57443:1;57432:13;57399:81;;;57403:3;;57069:421;56979:517;;;:::o;57672:1202::-;57794:18;57789:3;57786:27;57783:53;;;57816:18;;:::i;:::-;57845:93;57934:3;57894:38;57926:4;57920:11;57894:38;:::i;:::-;57888:4;57845:93;:::i;:::-;57964:1;57989:2;57984:3;57981:11;58006:1;58001:615;;;;58660:1;58677:3;58674:93;;;-1:-1:-1;58733:19:97;;;58720:33;58674:93;-1:-1:-1;;57629:1:97;57625:11;;;57621:24;57617:29;57607:40;57653:1;57649:11;;;57604:57;58780:78;;57974:894;;58001:615;56926:1;56919:14;;;56963:4;56950:18;;-1:-1:-1;;58037:17:97;;;58137:9;58159:229;58173:7;58170:1;58167:14;58159:229;;;58262:19;;;58249:33;58234:49;;58369:4;58354:20;;;;58322:1;58310:14;;;;58189:12;58159:229;;;58163:3;58416;58407:7;58404:16;58401:159;;;58540:1;58536:6;58530:3;58524;58521:1;58517:11;58513:21;58509:34;58505:39;58492:9;58487:3;58483:19;58470:33;58466:79;58458:6;58451:95;58401:159;;;58603:1;58597:3;58594:1;58590:11;58586:19;58580:4;58573:33;57974:894;;57672:1202;;;:::o;58879:315::-;59064:6;59053:9;59046:25;59107:2;59102;59091:9;59087:18;59080:30;59027:4;59127:61;59184:2;59173:9;59169:18;59161:6;59153;59127:61;:::i;59451:485::-;59527:6;59535;59543;59596:2;59584:9;59575:7;59571:23;59567:32;59564:52;;;59612:1;59609;59602:12;59564:52;59657:23;;;-1:-1:-1;59756:2:97;59741:18;;59728:32;59769;59728;59769;:::i;:::-;59451:485;;59820:7;;-1:-1:-1;;;59900:2:97;59885:18;;;;59872:32;;59451:485::o;59941:184::-;-1:-1:-1;;;59990:1:97;59983:88;60090:4;60087:1;60080:15;60114:4;60111:1;60104:15;61489:202;61556:6;61609:2;61597:9;61588:7;61584:23;61580:32;61577:52;;;61625:1;61622;61615:12;61577:52;61648:37;61675:9;61648:37;:::i;62321:475::-;62408:6;62416;62424;62477:2;62465:9;62456:7;62452:23;62448:32;62445:52;;;62493:1;62490;62483:12;62445:52;62538:16;;62623:2;62608:18;;62602:25;62538:16;;-1:-1:-1;62636:32:97;62602:25;62636:32;:::i;:::-;62760:2;62745:18;;;;62739:25;62321:475;;62687:7;;-1:-1:-1;62739:25:97;;62321:475;-1:-1:-1;;62321:475:97:o
Swarm Source
ipfs://1b8cf3e3f921ba8d94c9d11a75500ff4b930f86d1e5ad035d17793956ee9e950
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.