Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract contains unverified libraries: BLS
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:
Adapter
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 300 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20, Address} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {UUPSUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {IAdapter} from "./interfaces/IAdapter.sol"; import {IAdapterOwner} from "./interfaces/IAdapterOwner.sol"; import {IController} from "./interfaces/IController.sol"; import {IBasicRandcastConsumerBase} from "./interfaces/IBasicRandcastConsumerBase.sol"; import {RequestIdBase} from "./utils/RequestIdBase.sol"; import {BLS} from "./libraries/BLS.sol"; // solhint-disable-next-line no-global-import import "./utils/Utils.sol" as Utils; import {ChainHelper} from "./libraries/ChainHelper.sol"; contract Adapter is UUPSUpgradeable, IAdapter, IAdapterOwner, RequestIdBase, OwnableUpgradeable { using SafeERC20 for IERC20; using Address for address; // *Constants* uint16 public constant MAX_CONSUMERS = 100; uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; uint32 public constant RANDOMNESS_REWARD_GAS = 9000; uint32 public constant VERIFICATION_GAS_OVER_MINIMUM_THRESHOLD = 50000; uint32 public constant DEFAULT_MINIMUM_THRESHOLD = 3; // *State Variables* IController internal _controller; uint256 internal _cumulativeFlatFee; uint256 internal _cumulativeCommitterReward; uint256 internal _cumulativePartialSignatureReward; // Randomness Task State uint32 internal _lastAssignedGroupIndex; uint256 internal _lastRandomness; uint256 internal _randomnessCount; AdapterConfig internal _config; mapping(bytes32 => bytes32) internal _requestCommitments; /* consumerAddress - consumer */ mapping(address => Consumer) internal _consumers; /* subId - subscription */ mapping(uint64 => Subscription) internal _subscriptions; uint64 internal _currentSubId; // Referral Promotion ReferralConfig internal _referralConfig; // Flat Fee Promotion FlatFeeConfig internal _flatFeeConfig; // *Structs* // Note a nonce of 0 indicates an the consumer is not assigned to that subscription. struct Consumer { /* subId - nonce */ mapping(uint64 => uint64) nonces; uint64 lastSubscription; } struct Subscription { address owner; // Owner can fund/withdraw/cancel the sub. address requestedOwner; // For safely transferring sub ownership. address[] consumers; uint256 balance; // Token balance used for all consumer requests. uint256 inflightCost; // Upper cost for pending requests(except drastic exchange rate changes). mapping(bytes32 => uint256) inflightPayments; uint64 reqCount; // For fee tiers uint64 freeRequestCount; // Number of free requests(flat fee) for this sub. uint64 referralSubId; // uint64 reqCountInCurrentPeriod; // Number of requests in the current period. uint256 lastRequestTimestamp; // Timestamp of the last request. } // *Events* event AdapterConfigSet( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 gasAfterPaymentCalculation, uint32 gasExceptCallback, uint256 signatureTaskExclusiveWindow, uint256 rewardPerSignature, uint256 committerRewardPerSignature ); event FlatFeeConfigSet( FeeConfig flatFeeConfig, uint16 flatFeePromotionGlobalPercentage, bool isFlatFeePromotionEnabledPermanently, uint256 flatFeePromotionStartTimestamp, uint256 flatFeePromotionEndTimestamp ); event ReferralConfigSet( bool isReferralEnabled, uint16 freeRequestCountForReferrer, uint16 freeRequestCountForReferee ); event SubscriptionCreated(uint64 indexed subId, address indexed owner); event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); event SubscriptionConsumerAdded(uint64 indexed subId, address consumer); event SubscriptionReferralSet(uint64 indexed subId, uint64 indexed referralSubId); event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); event SubscriptionConsumerRemoved(uint64 indexed subId, address consumer); event RandomnessRequest( bytes32 indexed requestId, uint64 indexed subId, uint32 indexed groupIndex, RequestType requestType, bytes params, address sender, uint256 seed, uint16 requestConfirmations, uint32 callbackGasLimit, uint256 callbackMaxGasPrice, uint256 estimatedPayment ); event RandomnessRequestResult( bytes32 indexed requestId, uint32 indexed groupIndex, address indexed committer, address[] participantMembers, uint256 randommness, uint256 payment, uint256 flatFee, bool success ); event OvertimeRequestCanceled(bytes32 indexed requestId, uint64 indexed subId); // *Errors* error Reentrant(); error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); error TooManyConsumers(); error InsufficientBalanceWhenRequest(); error InsufficientBalanceWhenFulfill(); error InvalidConsumer(uint64 subId, address consumer); error InvalidSubscription(); error ReferralPromotionDisabled(); error SubscriptionAlreadyHasReferral(); error IdenticalSubscription(); error AtLeastOneRequestIsRequired(); error MustBeSubOwner(address owner); error NoAvailableGroups(); error NoCorrespondingRequest(); error IncorrectCommitment(); error InvalidRequestByEOA(); error TaskStillExclusive(); error TaskStillWithinRequestConfirmations(); error NotFromCommitter(); error GroupNotExist(uint256 groupIndex); error SenderNotController(); error PendingRequestExists(); error InvalidZeroAddress(); error GasLimitTooBig(uint32 have, uint32 want); error RequestNotExpired(); // *Modifiers* modifier onlySubOwner(uint64 subId) { address owner = _subscriptions[subId].owner; if (owner == address(0)) { revert InvalidSubscription(); } if (msg.sender != owner) { revert MustBeSubOwner(owner); } _; } modifier nonReentrant() { if (_config.reentrancyLock) { revert Reentrant(); } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address controller) public initializer { _controller = IController(controller); __Ownable_init(); } // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} // ============= // IAdapterOwner // ============= function setAdapterConfig( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 gasAfterPaymentCalculation, uint32 gasExceptCallback, uint256 signatureTaskExclusiveWindow, uint256 rewardPerSignature, uint256 committerRewardPerSignature ) external override(IAdapterOwner) onlyOwner { if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { revert InvalidRequestConfirmations( minimumRequestConfirmations, minimumRequestConfirmations, MAX_REQUEST_CONFIRMATIONS ); } _config = AdapterConfig({ minimumRequestConfirmations: minimumRequestConfirmations, maxGasLimit: maxGasLimit, gasAfterPaymentCalculation: gasAfterPaymentCalculation, gasExceptCallback: gasExceptCallback, signatureTaskExclusiveWindow: signatureTaskExclusiveWindow, rewardPerSignature: rewardPerSignature, committerRewardPerSignature: committerRewardPerSignature, reentrancyLock: false }); emit AdapterConfigSet( minimumRequestConfirmations, maxGasLimit, gasAfterPaymentCalculation, gasExceptCallback, signatureTaskExclusiveWindow, rewardPerSignature, committerRewardPerSignature ); } function setFlatFeeConfig( FeeConfig memory flatFeeConfig, uint16 flatFeePromotionGlobalPercentage, bool isFlatFeePromotionEnabledPermanently, uint256 flatFeePromotionStartTimestamp, uint256 flatFeePromotionEndTimestamp ) external override(IAdapterOwner) onlyOwner { _flatFeeConfig = FlatFeeConfig({ config: flatFeeConfig, flatFeePromotionGlobalPercentage: flatFeePromotionGlobalPercentage, isFlatFeePromotionEnabledPermanently: isFlatFeePromotionEnabledPermanently, flatFeePromotionStartTimestamp: flatFeePromotionStartTimestamp, flatFeePromotionEndTimestamp: flatFeePromotionEndTimestamp }); emit FlatFeeConfigSet( flatFeeConfig, flatFeePromotionGlobalPercentage, isFlatFeePromotionEnabledPermanently, flatFeePromotionStartTimestamp, flatFeePromotionEndTimestamp ); } function setReferralConfig( bool isReferralEnabled, uint16 freeRequestCountForReferrer, uint16 freeRequestCountForReferee ) external override(IAdapterOwner) onlyOwner { _referralConfig = ReferralConfig({ isReferralEnabled: isReferralEnabled, freeRequestCountForReferrer: freeRequestCountForReferrer, freeRequestCountForReferee: freeRequestCountForReferee }); emit ReferralConfigSet(isReferralEnabled, freeRequestCountForReferrer, freeRequestCountForReferee); } function setFreeRequestCount(uint64[] memory subIds, uint64[] memory freeRequestCounts) external override(IAdapterOwner) onlyOwner { for (uint256 i = 0; i < subIds.length; i++) { _subscriptions[subIds[i]].freeRequestCount = freeRequestCounts[i]; } } function ownerCancelSubscription(uint64 subId) external override(IAdapterOwner) onlyOwner { if (_subscriptions[subId].owner == address(0)) { revert InvalidSubscription(); } _cancelSubscriptionHelper(subId, _subscriptions[subId].owner); } // ============= // IAdapter // ============= function nodeWithdrawETH(address recipient, uint256 ethAmount) external override(IAdapter) { if (msg.sender != address(_controller)) { revert SenderNotController(); } payable(recipient).transfer(ethAmount); } function createSubscription() external override(IAdapter) nonReentrant returns (uint64) { _currentSubId++; _subscriptions[_currentSubId].owner = msg.sender; // flat fee free for the first request for each subscription _subscriptions[_currentSubId].freeRequestCount = 1; emit SubscriptionCreated(_currentSubId, msg.sender); return _currentSubId; } function addConsumer(uint64 subId, address consumer) external override(IAdapter) onlySubOwner(subId) nonReentrant { // Already maxed, cannot add any more consumers. if (_subscriptions[subId].consumers.length == MAX_CONSUMERS) { revert TooManyConsumers(); } if (_consumers[consumer].nonces[subId] != 0) { // Idempotence - do nothing if already added. // Ensures uniqueness in subscriptions[subId].consumers. return; } // Initialize the nonce to 1, indicating the consumer is allocated. _consumers[consumer].nonces[subId] = 1; _consumers[consumer].lastSubscription = subId; _subscriptions[subId].consumers.push(consumer); emit SubscriptionConsumerAdded(subId, consumer); } function removeConsumer(uint64 subId, address consumer) external override(IAdapter) onlySubOwner(subId) nonReentrant { if (_subscriptions[subId].inflightCost != 0) { revert PendingRequestExists(); } address[] memory consumers = _subscriptions[subId].consumers; if (consumers.length == 0) { revert InvalidConsumer(subId, consumer); } // Note bounded by MAX_CONSUMERS for (uint256 i = 0; i < consumers.length; i++) { if (consumers[i] == consumer) { _subscriptions[subId].consumers[i] = consumers[consumers.length - 1]; _subscriptions[subId].consumers.pop(); emit SubscriptionConsumerRemoved(subId, consumer); return; } } revert InvalidConsumer(subId, consumer); } function fundSubscription(uint64 subId) external payable override(IAdapter) nonReentrant { if (_subscriptions[subId].owner == address(0)) { revert InvalidSubscription(); } // We do not check that the msg.sender is the subscription owner, // anyone can fund a subscription. uint256 oldBalance = _subscriptions[subId].balance; _subscriptions[subId].balance += msg.value; emit SubscriptionFunded(subId, oldBalance, oldBalance + msg.value); } function setReferral(uint64 subId, uint64 referralSubId) external override(IAdapter) onlySubOwner(subId) nonReentrant { if (!_referralConfig.isReferralEnabled) { revert ReferralPromotionDisabled(); } if (_subscriptions[subId].owner == _subscriptions[referralSubId].owner) { revert IdenticalSubscription(); } if (_subscriptions[subId].referralSubId != 0) { revert SubscriptionAlreadyHasReferral(); } if (_subscriptions[subId].reqCount == 0 || _subscriptions[referralSubId].reqCount == 0) { revert AtLeastOneRequestIsRequired(); } _subscriptions[referralSubId].freeRequestCount += _referralConfig.freeRequestCountForReferrer; _subscriptions[subId].freeRequestCount += _referralConfig.freeRequestCountForReferee; _subscriptions[subId].referralSubId = referralSubId; emit SubscriptionReferralSet(subId, referralSubId); } function cancelSubscription(uint64 subId, address to) external override(IAdapter) onlySubOwner(subId) nonReentrant { if (to == address(0)) { revert InvalidZeroAddress(); } if (_subscriptions[subId].inflightCost != 0) { revert PendingRequestExists(); } _cancelSubscriptionHelper(subId, to); } function cancelOvertimeRequest(bytes32 requestId, RequestDetail calldata requestDetail) external override(IAdapter) onlySubOwner(requestDetail.subId) { if (_requestCommitments[requestId] == 0) { revert NoCorrespondingRequest(); } if ( _requestCommitments[requestId] != keccak256( abi.encode( requestId, requestDetail.subId, requestDetail.groupIndex, requestDetail.requestType, requestDetail.params, requestDetail.callbackContract, requestDetail.seed, requestDetail.requestConfirmations, requestDetail.callbackGasLimit, requestDetail.callbackMaxGasPrice, requestDetail.blockNum ) ) ) { revert IncorrectCommitment(); } uint256 blockNum24H = 1 days / ChainHelper.getBlockTime(); if (block.number < requestDetail.blockNum + blockNum24H) { revert RequestNotExpired(); } delete _requestCommitments[requestId]; _subscriptions[requestDetail.subId].inflightCost -= _subscriptions[requestDetail.subId].inflightPayments[requestId]; delete _subscriptions[requestDetail.subId].inflightPayments[requestId]; emit OvertimeRequestCanceled(requestId, requestDetail.subId); } function requestRandomness(RandomnessRequestParams calldata params) public virtual override(IAdapter) nonReentrant returns (bytes32) { RandomnessRequestParams memory p = params; // solhint-disable-next-line avoid-tx-origin if (msg.sender == tx.origin) { revert InvalidRequestByEOA(); } Subscription storage sub = _subscriptions[p.subId]; // Input validation using the subscription storage. if (sub.owner == address(0)) { revert InvalidSubscription(); } // Its important to ensure that the consumer is in fact who they say they // are, otherwise they could use someone else's subscription balance. // A nonce of 0 indicates consumer is not allocated to the sub. if (_consumers[msg.sender].nonces[p.subId] == 0) { revert InvalidConsumer(p.subId, msg.sender); } if ( p.requestConfirmations < _config.minimumRequestConfirmations || p.requestConfirmations > MAX_REQUEST_CONFIRMATIONS ) { revert InvalidRequestConfirmations( p.requestConfirmations, _config.minimumRequestConfirmations, MAX_REQUEST_CONFIRMATIONS ); } // No lower bound on the requested gas limit. A user could request 0 // and they would simply be billed for the proof verification and wouldn't be // able to do anything with the random value. if (p.callbackGasLimit > _config.maxGasLimit) { revert GasLimitTooBig(p.callbackGasLimit, _config.maxGasLimit); } // Choose current available group to handle randomness request(by round robin) _lastAssignedGroupIndex = uint32(_findGroupToAssignTask()); // Calculate requestId for the task uint256 rawSeed = _makeRandcastInputSeed(p.seed, p.subId, msg.sender, _consumers[msg.sender].nonces[p.subId]); _consumers[msg.sender].lastSubscription = p.subId; _consumers[msg.sender].nonces[p.subId] += 1; bytes32 requestId = _makeRequestId(rawSeed); (, uint256 groupSize) = _controller.getGroupThreshold(_lastAssignedGroupIndex); uint256 payment = _freezePaymentBySubscription(sub, requestId, uint32(groupSize), p.callbackGasLimit, p.callbackMaxGasPrice); _requestCommitments[requestId] = keccak256( abi.encode( requestId, p.subId, _lastAssignedGroupIndex, p.requestType, p.params, msg.sender, rawSeed, p.requestConfirmations, p.callbackGasLimit, p.callbackMaxGasPrice, block.number ) ); emit RandomnessRequest( requestId, p.subId, _lastAssignedGroupIndex, p.requestType, p.params, msg.sender, rawSeed, p.requestConfirmations, p.callbackGasLimit, p.callbackMaxGasPrice, payment ); return requestId; } function fulfillRandomness( uint32 groupIndex, bytes32 requestId, uint256 signature, RequestDetail calldata requestDetail, PartialSignature[] calldata partialSignatures ) public virtual override(IAdapter) nonReentrant { uint256 startGas = gasleft(); bytes32 commitment = _requestCommitments[requestId]; if (commitment == 0) { revert NoCorrespondingRequest(); } if ( commitment != keccak256( abi.encode( requestId, requestDetail.subId, requestDetail.groupIndex, requestDetail.requestType, requestDetail.params, requestDetail.callbackContract, requestDetail.seed, requestDetail.requestConfirmations, requestDetail.callbackGasLimit, requestDetail.callbackMaxGasPrice, requestDetail.blockNum ) ) ) { revert IncorrectCommitment(); } if (block.number < requestDetail.blockNum + requestDetail.requestConfirmations) { revert TaskStillWithinRequestConfirmations(); } if ( groupIndex != requestDetail.groupIndex && block.number <= requestDetail.blockNum + _config.signatureTaskExclusiveWindow ) { revert TaskStillExclusive(); } if (groupIndex >= _controller.getGroupCount()) { revert GroupNotExist(groupIndex); } address[] memory participantMembers = _verifySignature(groupIndex, requestDetail.seed, requestDetail.blockNum, signature, partialSignatures); delete _requestCommitments[requestId]; uint256 randomness = uint256(keccak256(abi.encode(signature))); _randomnessCount += 1; _lastRandomness = randomness; _controller.setLastOutput(randomness); // call user fulfill_randomness callback bool success = _fulfillCallback(requestId, randomness, requestDetail); (uint256 payment, uint256 flatFee) = _payBySubscription(_subscriptions[requestDetail.subId], requestId, partialSignatures.length, startGas); // rewardRandomness for participants _rewardRandomness(participantMembers, payment, flatFee); // Include payment in the event for tracking costs. emit RandomnessRequestResult( requestId, groupIndex, msg.sender, participantMembers, randomness, payment, flatFee, success ); } function getLastSubscription(address consumer) public view override(IAdapter) returns (uint64) { return _consumers[consumer].lastSubscription; } function getSubscription(uint64 subId) external view override(IAdapter) returns ( address owner, address[] memory consumers, uint256 balance, uint256 inflightCost, uint64 reqCount, uint64 freeRequestCount, uint64 referralSubId, uint64 reqCountInCurrentPeriod, uint256 lastRequestTimestamp ) { Subscription storage sub = _subscriptions[subId]; if (sub.owner == address(0)) { revert InvalidSubscription(); } return ( sub.owner, sub.consumers, sub.balance, sub.inflightCost, sub.reqCount, sub.freeRequestCount, sub.referralSubId, sub.reqCountInCurrentPeriod, sub.lastRequestTimestamp ); } function getPendingRequestCommitment(bytes32 requestId) public view override(IAdapter) returns (bytes32) { return _requestCommitments[requestId]; } function getLastAssignedGroupIndex() external view override(IAdapter) returns (uint256) { return _lastAssignedGroupIndex; } function getLastRandomness() external view override(IAdapter) returns (uint256) { return _lastRandomness; } function getRandomnessCount() external view override(IAdapter) returns (uint256) { return _randomnessCount; } function getCurrentSubId() external view override(IAdapter) returns (uint64) { return _currentSubId; } function getCumulativeData() external view override(IAdapter) returns (uint256, uint256, uint256) { return (_cumulativeFlatFee, _cumulativeCommitterReward, _cumulativePartialSignatureReward); } function getController() external view override(IAdapter) returns (address) { return address(_controller); } function getAdapterConfig() external view override(IAdapter) returns ( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 gasAfterPaymentCalculation, uint32 gasExceptCallback, uint256 signatureTaskExclusiveWindow, uint256 rewardPerSignature, uint256 committerRewardPerSignature ) { return ( _config.minimumRequestConfirmations, _config.maxGasLimit, _config.gasAfterPaymentCalculation, _config.gasExceptCallback, _config.signatureTaskExclusiveWindow, _config.rewardPerSignature, _config.committerRewardPerSignature ); } function getFlatFeeConfig() external view override(IAdapter) returns ( uint32 fulfillmentFlatFeeLinkPPMTier1, uint32 fulfillmentFlatFeeLinkPPMTier2, uint32 fulfillmentFlatFeeLinkPPMTier3, uint32 fulfillmentFlatFeeLinkPPMTier4, uint32 fulfillmentFlatFeeLinkPPMTier5, uint24 reqsForTier2, uint24 reqsForTier3, uint24 reqsForTier4, uint24 reqsForTier5, uint16 flatFeePromotionGlobalPercentage, bool isFlatFeePromotionEnabledPermanently, uint256 flatFeePromotionStartTimestamp, uint256 flatFeePromotionEndTimestamp ) { FeeConfig memory fc = _flatFeeConfig.config; return ( fc.fulfillmentFlatFeeEthPPMTier1, fc.fulfillmentFlatFeeEthPPMTier2, fc.fulfillmentFlatFeeEthPPMTier3, fc.fulfillmentFlatFeeEthPPMTier4, fc.fulfillmentFlatFeeEthPPMTier5, fc.reqsForTier2, fc.reqsForTier3, fc.reqsForTier4, fc.reqsForTier5, _flatFeeConfig.flatFeePromotionGlobalPercentage, _flatFeeConfig.isFlatFeePromotionEnabledPermanently, _flatFeeConfig.flatFeePromotionStartTimestamp, _flatFeeConfig.flatFeePromotionEndTimestamp ); } function getReferralConfig() external view override(IAdapter) returns (bool isReferralEnabled, uint16 freeRequestCountForReferrer, uint16 freeRequestCountForReferee) { return ( _referralConfig.isReferralEnabled, _referralConfig.freeRequestCountForReferrer, _referralConfig.freeRequestCountForReferee ); } function getFeeTier(uint64 reqCount) public view override(IAdapter) returns (uint32) { FeeConfig memory fc = _flatFeeConfig.config; if (reqCount <= fc.reqsForTier2) { return fc.fulfillmentFlatFeeEthPPMTier1; } if (fc.reqsForTier2 < reqCount && reqCount <= fc.reqsForTier3) { return fc.fulfillmentFlatFeeEthPPMTier2; } if (fc.reqsForTier3 < reqCount && reqCount <= fc.reqsForTier4) { return fc.fulfillmentFlatFeeEthPPMTier3; } if (fc.reqsForTier4 < reqCount && reqCount <= fc.reqsForTier5) { return fc.fulfillmentFlatFeeEthPPMTier4; } return fc.fulfillmentFlatFeeEthPPMTier5; } function estimatePaymentAmountInETH( uint32 callbackGasLimit, uint32 gasExceptCallback, uint32 fulfillmentFlatFeeEthPPM, uint256 weiPerUnitGas, uint32 groupSize ) public view override(IAdapter) returns (uint256) { // we estimate 1.5x the cost of the fulfillment calldata uint256 estimatedFulfillmentL1CostWei = ChainHelper.getTxL1GasFees(ChainHelper.getFulfillmentTxL1GasUsed(groupSize)) * 3 / 2; uint256 paymentNoFee = weiPerUnitGas * (gasExceptCallback + callbackGasLimit) + estimatedFulfillmentL1CostWei; return (paymentNoFee + 1e12 * uint256(fulfillmentFlatFeeEthPPM)); } // ============= // Internal // ============= function _rewardRandomness(address[] memory participantMembers, uint256 payment, uint256 flatFee) internal { _cumulativeCommitterReward += _config.committerRewardPerSignature; _cumulativePartialSignatureReward += _config.rewardPerSignature * participantMembers.length; address[] memory committer = new address[](1); committer[0] = msg.sender; _controller.addReward(committer, payment - flatFee, _config.committerRewardPerSignature); _controller.addReward(participantMembers, flatFee / participantMembers.length, _config.rewardPerSignature); } function _fulfillCallback(bytes32 requestId, uint256 randomness, RequestDetail memory requestDetail) internal returns (bool success) { IBasicRandcastConsumerBase b; bytes memory resp; if (requestDetail.requestType == RequestType.Randomness) { resp = abi.encodeWithSelector(b.rawFulfillRandomness.selector, requestId, randomness); } else if (requestDetail.requestType == RequestType.RandomWords) { uint32 numWords = abi.decode(requestDetail.params, (uint32)); uint256[] memory randomWords = new uint256[](numWords); for (uint256 i = 0; i < numWords; i++) { randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); } resp = abi.encodeWithSelector(b.rawFulfillRandomWords.selector, requestId, randomWords); } else if (requestDetail.requestType == RequestType.Shuffling) { uint32 upper = abi.decode(requestDetail.params, (uint32)); uint256[] memory shuffledArray = Utils.shuffle(upper, randomness); resp = abi.encodeWithSelector(b.rawFulfillShuffledArray.selector, requestId, shuffledArray); } // Call with explicitly the amount of callback gas requested // Important to not let them exhaust the gas budget and avoid oracle payment. // Do not allow any non-view/non-pure coordinator functions to be called // during the consumers callback code via reentrancyLock. // Note that callWithExactGas will revert if we do not have sufficient gas // to give the callee their requested amount. _config.reentrancyLock = true; success = Utils.callWithExactGas(requestDetail.callbackGasLimit, requestDetail.callbackContract, resp); _config.reentrancyLock = false; } function _freezePaymentBySubscription( Subscription storage sub, bytes32 requestId, uint32 groupSize, uint32 callbackGasLimit, uint256 callbackMaxGasPrice ) internal returns (uint256) { uint64 reqCount; if (_flatFeeConfig.isFlatFeePromotionEnabledPermanently) { reqCount = sub.reqCount; } else if ( _flatFeeConfig //solhint-disable-next-line not-rely-on-time .flatFeePromotionStartTimestamp <= block.timestamp //solhint-disable-next-line not-rely-on-time && block.timestamp <= _flatFeeConfig.flatFeePromotionEndTimestamp ) { if (sub.lastRequestTimestamp < _flatFeeConfig.flatFeePromotionStartTimestamp) { reqCount = 1; } else { reqCount = sub.reqCountInCurrentPeriod + 1; } } // Estimate upper cost of this fulfillment. uint256 payment = estimatePaymentAmountInETH( callbackGasLimit, _config.gasExceptCallback + RANDOMNESS_REWARD_GAS * groupSize + VERIFICATION_GAS_OVER_MINIMUM_THRESHOLD * (groupSize - DEFAULT_MINIMUM_THRESHOLD), sub.freeRequestCount > 0 ? 0 : (getFeeTier(reqCount) * _flatFeeConfig.flatFeePromotionGlobalPercentage / 100), callbackMaxGasPrice, groupSize ); if (sub.balance - sub.inflightCost < payment) { revert InsufficientBalanceWhenRequest(); } sub.inflightCost += payment; sub.inflightPayments[requestId] = payment; return payment; } function _payBySubscription( Subscription storage sub, bytes32 requestId, uint256 partialSignersCount, uint256 startGas ) internal returns (uint256, uint256) { // Increment the req count for fee tier selection. sub.reqCount += 1; uint64 reqCount; if (_flatFeeConfig.isFlatFeePromotionEnabledPermanently) { reqCount = sub.reqCount; } else if ( _flatFeeConfig //solhint-disable-next-line not-rely-on-time .flatFeePromotionStartTimestamp <= block.timestamp //solhint-disable-next-line not-rely-on-time && block.timestamp <= _flatFeeConfig.flatFeePromotionEndTimestamp ) { if (sub.lastRequestTimestamp < _flatFeeConfig.flatFeePromotionStartTimestamp) { sub.reqCountInCurrentPeriod = 1; } else { sub.reqCountInCurrentPeriod += 1; } reqCount = sub.reqCountInCurrentPeriod; } //solhint-disable-next-line not-rely-on-time sub.lastRequestTimestamp = block.timestamp; uint256 flatFee; if (sub.freeRequestCount > 0) { sub.freeRequestCount -= 1; } else { // The flat eth fee is specified in millionths of eth, if _config.fulfillmentFlatFeeEthPPM = 1 // 1 eth / 1e6 = 1e18 eth wei / 1e6 = 1e12 eth wei. flatFee = 1e12 * uint256(getFeeTier(reqCount)) * _flatFeeConfig.flatFeePromotionGlobalPercentage / 100; } // We want to charge users exactly for how much gas they use in their callback. // The gasAfterPaymentCalculation is meant to cover these additional operations where we // decrement the subscription balance and increment the groups withdrawable balance. uint256 payment = _calculatePaymentAmountInETH( startGas, _config.gasAfterPaymentCalculation + RANDOMNESS_REWARD_GAS * partialSignersCount, flatFee, tx.gasprice ); if (sub.balance < payment) { revert InsufficientBalanceWhenFulfill(); } sub.inflightCost -= sub.inflightPayments[requestId]; delete sub.inflightPayments[requestId]; sub.balance -= payment; _cumulativeFlatFee += flatFee; return (payment, flatFee); } function _cancelSubscriptionHelper(uint64 subId, address to) internal nonReentrant { uint256 balance = _subscriptions[subId].balance; delete _subscriptions[subId].owner; emit SubscriptionCanceled(subId, to, balance); payable(to).transfer(balance); } // Get the amount of gas used for fulfillment function _calculatePaymentAmountInETH( uint256 startGas, uint256 gasAfterPaymentCalculation, uint256 flatFee, uint256 weiPerUnitGas ) internal view returns (uint256) { uint256 paymentNoFee = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + ChainHelper.getCurrentTxL1GasFees(); return paymentNoFee + flatFee; } function _findGroupToAssignTask() internal view returns (uint256) { uint256[] memory validGroupIndices = _controller.getValidGroupIndices(); if (validGroupIndices.length == 0) { revert NoAvailableGroups(); } uint256 groupCount = _controller.getGroupCount(); uint256 currentAssignedGroupIndex = (_lastAssignedGroupIndex + 1) % groupCount; while (!Utils.containElement(validGroupIndices, currentAssignedGroupIndex)) { currentAssignedGroupIndex = (currentAssignedGroupIndex + 1) % groupCount; } return currentAssignedGroupIndex; } function _verifySignature( uint256 groupIndex, uint256 seed, uint256 blockNum, uint256 signature, PartialSignature[] memory partialSignatures ) internal view returns (address[] memory participantMembers) { if (!BLS.isValid(signature)) { revert BLS.InvalidSignatureFormat(); } if (partialSignatures.length == 0) { revert BLS.EmptyPartialSignatures(); } IController.Group memory g = _controller.getGroup(groupIndex); if (!Utils.containElement(g.committers, msg.sender)) { revert NotFromCommitter(); } bytes memory actualSeed = abi.encodePacked(seed, blockNum); uint256[2] memory message = BLS.hashToPoint(actualSeed); // verify tss-aggregation signature for randomness if (!BLS.verifySingle(BLS.decompress(signature), g.publicKey, message)) { revert BLS.InvalidSignature(); } // verify bls-aggregation signature for incentivizing worker list uint256[2][] memory partials = new uint256[2][](partialSignatures.length); uint256[4][] memory pubkeys = new uint256[4][](partialSignatures.length); participantMembers = new address[](partialSignatures.length); for (uint256 i = 0; i < partialSignatures.length; i++) { if (!BLS.isValid(partialSignatures[i].partialSignature)) { revert BLS.InvalidPartialSignatureFormat(); } partials[i] = BLS.decompress(partialSignatures[i].partialSignature); pubkeys[i] = g.members[partialSignatures[i].index].partialPublicKey; participantMembers[i] = g.members[partialSignatures[i].index].nodeIdAddress; } if (!BLS.verifyPartials(partials, pubkeys, message)) { revert BLS.InvalidPartialSignatures(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../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. * * 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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.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. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @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() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @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() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @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 override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IRequestTypeBase} from "./IRequestTypeBase.sol"; interface IAdapter is IRequestTypeBase { struct PartialSignature { uint256 index; uint256 partialSignature; } struct RandomnessRequestParams { RequestType requestType; bytes params; uint64 subId; uint256 seed; uint16 requestConfirmations; uint32 callbackGasLimit; uint256 callbackMaxGasPrice; } struct RequestDetail { uint64 subId; uint32 groupIndex; RequestType requestType; bytes params; address callbackContract; uint256 seed; uint16 requestConfirmations; uint32 callbackGasLimit; uint256 callbackMaxGasPrice; uint256 blockNum; } // controller transaction function nodeWithdrawETH(address recipient, uint256 ethAmount) external; // consumer contract transaction function requestRandomness(RandomnessRequestParams calldata params) external returns (bytes32); function fulfillRandomness( uint32 groupIndex, bytes32 requestId, uint256 signature, RequestDetail calldata requestDetail, PartialSignature[] calldata partialSignatures ) external; // user transaction function createSubscription() external returns (uint64); function addConsumer(uint64 subId, address consumer) external; function fundSubscription(uint64 subId) external payable; function setReferral(uint64 subId, uint64 referralSubId) external; function cancelSubscription(uint64 subId, address to) external; function removeConsumer(uint64 subId, address consumer) external; // delete the request that cannot be fulfilled, triggered by user themselves function cancelOvertimeRequest(bytes32 requestId, RequestDetail calldata requestDetail) external; // view function getLastSubscription(address consumer) external view returns (uint64); function getSubscription(uint64 subId) external view returns ( address owner, address[] memory consumers, uint256 balance, uint256 inflightCost, uint64 reqCount, uint64 freeRequestCount, uint64 referralSubId, uint64 reqCountInCurrentPeriod, uint256 lastRequestTimestamp ); function getPendingRequestCommitment(bytes32 requestId) external view returns (bytes32); function getLastAssignedGroupIndex() external view returns (uint256); function getLastRandomness() external view returns (uint256); function getRandomnessCount() external view returns (uint256); function getCurrentSubId() external view returns (uint64); function getCumulativeData() external view returns (uint256, uint256, uint256); function getController() external view returns (address); function getAdapterConfig() external view returns ( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 gasAfterPaymentCalculation, uint32 gasExceptCallback, uint256 signatureTaskExclusiveWindow, uint256 rewardPerSignature, uint256 committerRewardPerSignature ); function getFlatFeeConfig() external view returns ( uint32 fulfillmentFlatFeeLinkPPMTier1, uint32 fulfillmentFlatFeeLinkPPMTier2, uint32 fulfillmentFlatFeeLinkPPMTier3, uint32 fulfillmentFlatFeeLinkPPMTier4, uint32 fulfillmentFlatFeeLinkPPMTier5, uint24 reqsForTier2, uint24 reqsForTier3, uint24 reqsForTier4, uint24 reqsForTier5, uint16 flatFeePromotionGlobalPercentage, bool isFlatFeePromotionEnabledPermanently, uint256 flatFeePromotionStartTimestamp, uint256 flatFeePromotionEndTimestamp ); function getReferralConfig() external view returns (bool isReferralEnabled, uint16 freeRequestCountForReferrer, uint16 freeRequestCountForReferee); /* * @notice Compute fee based on the request count * @param reqCount number of requests * @return feePPM fee in ARPA PPM */ function getFeeTier(uint64 reqCount) external view returns (uint32); // Estimate the amount of gas used for fulfillment function estimatePaymentAmountInETH( uint32 callbackGasLimit, uint32 gasExceptCallback, uint32 fulfillmentFlatFeeEthPPM, uint256 weiPerUnitGas, uint32 groupSize ) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IAdapterOwner { struct AdapterConfig { // Minimum number of blocks a request must wait before being fulfilled. uint16 minimumRequestConfirmations; // Maximum gas limit for fulfillRandomness requests. uint32 maxGasLimit; // Reentrancy protection. bool reentrancyLock; // Gas to cover group payment after we calculate the payment. // We make it configurable in case those operations are repriced. uint32 gasAfterPaymentCalculation; // Gas except callback during fulfillment of randomness. Only used for estimating inflight cost. uint32 gasExceptCallback; // The assigned group is exclusive for fulfilling the task within this block window uint256 signatureTaskExclusiveWindow; // reward per signature for every participating node uint256 rewardPerSignature; // reward per signature for the committer uint256 committerRewardPerSignature; } struct FeeConfig { // Flat fee charged per fulfillment in millionths of arpa uint32 fulfillmentFlatFeeEthPPMTier1; uint32 fulfillmentFlatFeeEthPPMTier2; uint32 fulfillmentFlatFeeEthPPMTier3; uint32 fulfillmentFlatFeeEthPPMTier4; uint32 fulfillmentFlatFeeEthPPMTier5; uint24 reqsForTier2; uint24 reqsForTier3; uint24 reqsForTier4; uint24 reqsForTier5; } struct FlatFeeConfig { FeeConfig config; uint16 flatFeePromotionGlobalPercentage; bool isFlatFeePromotionEnabledPermanently; uint256 flatFeePromotionStartTimestamp; uint256 flatFeePromotionEndTimestamp; } struct ReferralConfig { bool isReferralEnabled; uint16 freeRequestCountForReferrer; uint16 freeRequestCountForReferee; } /** * @notice Sets the configuration of the adapter * @param minimumRequestConfirmations global min for request confirmations * @param maxGasLimit global max for request gas limit * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement * @param signatureTaskExclusiveWindow window in which a signature task is exclusive to the assigned group * @param rewardPerSignature reward per signature for every participating node * @param committerRewardPerSignature reward per signature for the committer */ function setAdapterConfig( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 gasAfterPaymentCalculation, uint32 gasExceptCallback, uint256 signatureTaskExclusiveWindow, uint256 rewardPerSignature, uint256 committerRewardPerSignature ) external; /** * @notice Sets the flat fee configuration of the adapter * @param flatFeeConfig flat fee tier configuration * @param flatFeePromotionGlobalPercentage global percentage of flat fee promotion * @param isFlatFeePromotionEnabledPermanently whether flat fee promotion is enabled permanently * @param flatFeePromotionStartTimestamp flat fee promotion start timestamp * @param flatFeePromotionEndTimestamp flat fee promotion end timestamp */ function setFlatFeeConfig( FeeConfig memory flatFeeConfig, uint16 flatFeePromotionGlobalPercentage, bool isFlatFeePromotionEnabledPermanently, uint256 flatFeePromotionStartTimestamp, uint256 flatFeePromotionEndTimestamp ) external; /** * @notice Sets the referral configuration of the adapter * @param isReferralEnabled whether referral is enabled * @param freeRequestCountForReferrer free request count for referrer * @param freeRequestCountForReferee free request count for referee */ function setReferralConfig( bool isReferralEnabled, uint16 freeRequestCountForReferrer, uint16 freeRequestCountForReferee ) external; /** * @notice Sets free request count for subscriptions * @param subIds subscription ids * @param freeRequestCounts free request count for each subscription */ function setFreeRequestCount(uint64[] memory subIds, uint64[] memory freeRequestCounts) external; /** * @notice Owner cancel subscription, sends remaining eth directly to the subscription owner * @param subId subscription id * @dev notably can be called even if there are pending requests */ function ownerCancelSubscription(uint64 subId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IController { struct Group { uint256 index; uint256 epoch; uint256 size; uint256 threshold; Member[] members; address[] committers; CommitCache[] commitCacheList; bool isStrictlyMajorityConsensusReached; uint256[4] publicKey; } struct Member { address nodeIdAddress; uint256[4] partialPublicKey; } struct CommitResult { uint256 groupEpoch; uint256[4] publicKey; address[] disqualifiedNodes; } struct CommitCache { address[] nodeIdAddress; CommitResult commitResult; } struct Node { address idAddress; bytes dkgPublicKey; bool state; uint256 pendingUntilBlock; } struct CommitDkgParams { uint256 groupIndex; uint256 groupEpoch; bytes publicKey; bytes partialPublicKey; address[] disqualifiedNodes; } // node transaction function nodeRegister(bytes calldata dkgPublicKey) external; function nodeActivate() external; function nodeQuit() external; function changeDkgPublicKey(bytes calldata dkgPublicKey) external; function commitDkg(CommitDkgParams memory params) external; function postProcessDkg(uint256 groupIndex, uint256 groupEpoch) external; function nodeWithdraw(address recipient) external; // adapter transaction function addReward(address[] memory nodes, uint256 ethAmount, uint256 arpaAmount) external; function setLastOutput(uint256 lastOutput) external; // view function getControllerConfig() external view returns ( address stakingContractAddress, address adapterContractAddress, uint256 nodeStakingAmount, uint256 disqualifiedNodePenaltyAmount, uint256 defaultNumberOfCommitters, uint256 defaultDkgPhaseDuration, uint256 groupMaxCapacity, uint256 idealNumberOfGroups, uint256 pendingBlockAfterQuit, uint256 dkgPostProcessReward ); /// @notice Get list of all group indexes where group.isStrictlyMajorityConsensusReached == true /// @return uint256[] List of valid group indexes function getValidGroupIndices() external view returns (uint256[] memory); function getGroupEpoch() external view returns (uint256); function getGroupCount() external view returns (uint256); function getGroup(uint256 index) external view returns (Group memory); function getGroupThreshold(uint256 groupIndex) external view returns (uint256, uint256); function getNode(address nodeAddress) external view returns (Node memory); function getMember(uint256 groupIndex, uint256 memberIndex) external view returns (Member memory); /// @notice Get the group index and member index of a given node. function getBelongingGroup(address nodeAddress) external view returns (int256, int256); function getCoordinator(uint256 groupIndex) external view returns (address); function getNodeWithdrawableTokens(address nodeAddress) external view returns (uint256, uint256); function getLastOutput() external view returns (uint256); /// @notice Check to see if a group has a partial public key registered for a given node. /// @return bool True if the node has a partial public key registered for the group. function isPartialKeyRegistered(uint256 groupIndex, address nodeIdAddress) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IBasicRandcastConsumerBase { function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external; function rawFulfillRandomWords(bytes32 requestId, uint256[] memory randomWords) external; function rawFulfillShuffledArray(bytes32 requestId, uint256[] memory shuffledArray) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; contract RequestIdBase { function _makeRandcastInputSeed(uint256 userSeed, uint64 subId, address requester, uint256 nonce) internal view returns (uint256) { return uint256(keccak256(abi.encode(block.chainid, userSeed, subId, requester, nonce))); } function _makeRequestId(uint256 inputSeed) internal pure returns (bytes32) { return keccak256(abi.encodePacked(inputSeed)); } }
// SPDX-License-Identifier: LGPL 3.0 pragma solidity ^0.8.18; import {BN256G2} from "./BN256G2.sol"; /** * @title BLS operations on bn254 curve * @author ARPA-Network adapted from https://github.com/ChihChengLiang/bls_solidity_python * @dev Homepage: https://github.com/ARPA-Network/BLS-TSS-Network * Signature and Point hashed to G1 are represented by affine coordinate in big-endian order, deserialized from compressed format. * Public key is represented and serialized by affine coordinate Q-x-re(x0), Q-x-im(x1), Q-y-re(y0), Q-y-im(y1) in big-endian order. */ library BLS { // Field order uint256 public constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // Negated genarator of G2 uint256 public constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; uint256 public constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; uint256 public constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052; uint256 public constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653; uint256 public constant FIELD_MASK = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; error MustNotBeInfinity(); error InvalidPublicKeyEncoding(); error InvalidSignatureFormat(); error InvalidSignature(); error InvalidPartialSignatureFormat(); error InvalidPartialSignatures(); error EmptyPartialSignatures(); error InvalidPublicKey(); error InvalidPartialPublicKey(); function verifySingle(uint256[2] memory signature, uint256[4] memory pubkey, uint256[2] memory message) public view returns (bool) { uint256[12] memory input = [ signature[0], signature[1], N_G2_X1, N_G2_X0, N_G2_Y1, N_G2_Y0, message[0], message[1], pubkey[1], pubkey[0], pubkey[3], pubkey[2] ]; uint256[1] memory out; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, input, 384, out, 0x20) switch success case 0 { invalid() } } require(success, ""); return out[0] != 0; } function verifyPartials(uint256[2][] memory partials, uint256[4][] memory pubkeys, uint256[2] memory message) public view returns (bool) { uint256[2] memory aggregatedSignature; uint256[4] memory aggregatedPublicKey; for (uint256 i = 0; i < partials.length; i++) { aggregatedSignature = addPoints(aggregatedSignature, partials[i]); aggregatedPublicKey = BN256G2.ecTwistAdd(aggregatedPublicKey, pubkeys[i]); } uint256[12] memory input = [ aggregatedSignature[0], aggregatedSignature[1], N_G2_X1, N_G2_X0, N_G2_Y1, N_G2_Y0, message[0], message[1], aggregatedPublicKey[1], aggregatedPublicKey[0], aggregatedPublicKey[3], aggregatedPublicKey[2] ]; uint256[1] memory out; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, input, 384, out, 0x20) switch success case 0 { invalid() } } require(success, ""); return out[0] != 0; } // TODO a simple hash and increment implementation, can be improved later function hashToPoint(bytes memory data) public view returns (uint256[2] memory p) { bool found; bytes32 candidateHash = keccak256(data); while (true) { (p, found) = mapToPoint(candidateHash); if (found) { break; } candidateHash = keccak256(bytes.concat(candidateHash)); } } // we take the y-coordinate as the lexicographically largest of the two associated with the encoded x-coordinate function mapToPoint(bytes32 _x) internal view returns (uint256[2] memory p, bool found) { uint256 y; uint256 x = uint256(_x) % N; (y, found) = deriveYOnG1(x); if (found) { p[0] = x; p[1] = y > N / 2 ? N - y : y; } } function deriveYOnG1(uint256 x) internal view returns (uint256, bool) { uint256 y; y = mulmod(x, x, N); y = mulmod(y, x, N); y = addmod(y, 3, N); return sqrt(y); } function isValidPublicKey(uint256[4] memory publicKey) public pure returns (bool) { if ((publicKey[0] >= N) || (publicKey[1] >= N) || (publicKey[2] >= N || (publicKey[3] >= N))) { return false; } else { return isOnCurveG2(publicKey); } } function fromBytesPublicKey(bytes memory point) public pure returns (uint256[4] memory pubkey) { if (point.length != 128) { revert InvalidPublicKeyEncoding(); } uint256 x0; uint256 x1; uint256 y0; uint256 y1; // solhint-disable-next-line no-inline-assembly assembly { // look the first 32 bytes of a bytes struct is its length x0 := mload(add(point, 32)) x1 := mload(add(point, 64)) y0 := mload(add(point, 96)) y1 := mload(add(point, 128)) } pubkey = [x0, x1, y0, y1]; } function decompress(uint256 compressedSignature) public view returns (uint256[2] memory uncompressed) { uint256 x = compressedSignature & FIELD_MASK; // The most significant bit, when set, indicates that the y-coordinate of the point // is the lexicographically largest of the two associated values. // The second-most significant bit indicates that the point is at infinity. If this bit is set, // the remaining bits of the group element's encoding should be set to zero. // We don't accept infinity as valid signature. uint256 decision = compressedSignature >> 254; if (decision & 1 == 1) { revert MustNotBeInfinity(); } uint256 y; (y,) = deriveYOnG1(x); // If the following two conditions or their negative forms are not met at the same time, get the negative y. // 1. The most significant bit of compressed signature is set // 2. The y we recovered first is the lexicographically largest if (((decision >> 1) ^ (y > N / 2 ? 1 : 0)) == 1) { y = N - y; } return [x, y]; } function isValid(uint256 compressedSignature) public view returns (bool) { uint256 x = compressedSignature & FIELD_MASK; if (x >= N) { return false; } else if (x == 0) { return false; } return isOnCurveG1(x); } function isOnCurveG1(uint256[2] memory point) internal pure returns (bool _isOnCurve) { // solhint-disable-next-line no-inline-assembly assembly { let t0 := mload(point) let t1 := mload(add(point, 32)) let t2 := mulmod(t0, t0, N) t2 := mulmod(t2, t0, N) t2 := addmod(t2, 3, N) t1 := mulmod(t1, t1, N) _isOnCurve := eq(t1, t2) } } function isOnCurveG1(uint256 x) internal view returns (bool _isOnCurve) { bool callSuccess; // solhint-disable-next-line no-inline-assembly assembly { let t0 := x let t1 := mulmod(t0, t0, N) t1 := mulmod(t1, t0, N) // x ^ 3 + b t1 := addmod(t1, 3, N) let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), t1) // (N - 1) / 2 = 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3 mstore(add(freemem, 0x80), 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3) // N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 mstore(add(freemem, 0xA0), 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) callSuccess := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) _isOnCurve := eq(1, mload(freemem)) } } function isOnCurveG2(uint256[4] memory point) internal pure returns (bool _isOnCurve) { // solhint-disable-next-line no-inline-assembly assembly { // x0, x1 let t0 := mload(point) let t1 := mload(add(point, 32)) // x0 ^ 2 let t2 := mulmod(t0, t0, N) // x1 ^ 2 let t3 := mulmod(t1, t1, N) // 3 * x0 ^ 2 let t4 := add(add(t2, t2), t2) // 3 * x1 ^ 2 let t5 := addmod(add(t3, t3), t3, N) // x0 * (x0 ^ 2 - 3 * x1 ^ 2) t2 := mulmod(add(t2, sub(N, t5)), t0, N) // x1 * (3 * x0 ^ 2 - x1 ^ 2) t3 := mulmod(add(t4, sub(N, t3)), t1, N) // x ^ 3 + b t0 := addmod(t2, 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5, N) t1 := addmod(t3, 0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2, N) // y0, y1 t2 := mload(add(point, 64)) t3 := mload(add(point, 96)) // y ^ 2 t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N) t3 := mulmod(shl(1, t2), t3, N) // y ^ 2 == x ^ 3 + b _isOnCurve := and(eq(t0, t4), eq(t1, t3)) } } function sqrt(uint256 xx) internal view returns (uint256 x, bool hasRoot) { bool callSuccess; // solhint-disable-next-line no-inline-assembly assembly { let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), xx) // this is enabled by N % 4 = 3 and Fermat's little theorem // (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 mstore(add(freemem, 0x80), 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52) // N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 mstore(add(freemem, 0xA0), 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) callSuccess := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) x := mload(freemem) hasRoot := eq(xx, mulmod(x, x, N)) } require(callSuccess, "BLS: sqrt modexp call failed"); } /// @notice Add two points in G1 function addPoints(uint256[2] memory p1, uint256[2] memory p2) internal view returns (uint256[2] memory ret) { uint256[4] memory input; input[0] = p1[0]; input[1] = p1[1]; input[2] = p2[0]; input[3] = p2[1]; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 6, input, 0xc0, ret, 0x60) } // solhint-disable-next-line reason-string require(success); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) // and some arithmetic operations. uint256 constant GAS_FOR_CALL_EXACT_CHECK = 5_000; function containElement(uint256[] memory arr, uint256 element) pure returns (bool) { for (uint256 i = 0; i < arr.length; i++) { if (arr[i] == element) { return true; } } return false; } function containElement(address[] memory arr, address element) pure returns (bool) { for (uint256 i = 0; i < arr.length; i++) { if (arr[i] == element) { return true; } } return false; } /** * @dev returns the minimum threshold for a group of size groupSize */ function minimumThreshold(uint256 groupSize) pure returns (uint256) { return groupSize / 2 + 1; } /** * @dev choose one random index from an array. */ function pickRandomIndex(uint256 seed, uint256 length) pure returns (uint256) { return uint256(keccak256(abi.encodePacked(seed))) % length; } /** * @dev choose "count" random indices from "indices" array. */ function pickRandomIndex(uint256 seed, uint256[] memory indices, uint256 count) pure returns (uint256[] memory) { uint256[] memory chosenIndices = new uint256[](count); // Create copy of indices to avoid modifying original array. uint256[] memory remainingIndices = new uint256[](indices.length); for (uint256 i = 0; i < indices.length; i++) { remainingIndices[i] = indices[i]; } uint256 remainingCount = remainingIndices.length; for (uint256 i = 0; i < count; i++) { uint256 index = uint256(keccak256(abi.encodePacked(seed, i))) % remainingCount; chosenIndices[i] = remainingIndices[index]; remainingIndices[index] = remainingIndices[remainingCount - 1]; remainingCount--; } return chosenIndices; } /** * @dev iterates through list of members and remove disqualified nodes. */ function getNonDisqualifiedMajorityMembers(address[] memory nodeAddresses, address[] memory disqualifiedNodes) pure returns (address[] memory) { address[] memory majorityMembers = new address[](nodeAddresses.length); uint256 majorityMembersLength = 0; for (uint256 i = 0; i < nodeAddresses.length; i++) { if (!containElement(disqualifiedNodes, nodeAddresses[i])) { majorityMembers[majorityMembersLength] = nodeAddresses[i]; majorityMembersLength++; } } // remove trailing zero addresses return trimTrailingElements(majorityMembers, majorityMembersLength); } function trimTrailingElements(uint256[] memory arr, uint256 newLength) pure returns (uint256[] memory) { uint256[] memory output = new uint256[](newLength); for (uint256 i = 0; i < newLength; i++) { output[i] = arr[i]; } return output; } function trimTrailingElements(address[] memory arr, uint256 newLength) pure returns (address[] memory) { address[] memory output = new address[](newLength); for (uint256 i = 0; i < newLength; i++) { output[i] = arr[i]; } return output; } /** * @dev calls target address with exactly gasAmount gas and data as calldata * or reverts if at least gasAmount gas is not available. */ function callWithExactGas(uint256 gasAmount, address target, bytes memory data) returns (bool success) { // solhint-disable-next-line no-inline-assembly assembly { let g := gas() // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). // We want to ensure that we revert if gasAmount > 63//64*gas available // as we do not want to provide them with less, however that check itself costs // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able // to revert if gasAmount > 63//64*gas available. if lt(g, GAS_FOR_CALL_EXACT_CHECK) { revert(0, 0) } g := sub(g, GAS_FOR_CALL_EXACT_CHECK) // if g - g//64 <= gasAmount, revert // (we subtract g//64 because of EIP-150) if iszero(gt(sub(g, div(g, 64)), gasAmount)) { revert(0, 0) } // solidity calls check that a contract actually exists at the destination, so we do the same if iszero(extcodesize(target)) { revert(0, 0) } // call and return whether we succeeded. ignore return data // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) } return success; } function shuffle(uint256 upper, uint256 randomness) pure returns (uint256[] memory) { uint256[] memory arr = new uint256[](upper); for (uint256 k = 0; k < upper; k++) { arr[k] = k; } uint256 i = arr.length; uint256 j; uint256 t; while (--i > 0) { j = randomness % i; randomness = uint256(keccak256(abi.encode(randomness))); t = arr[i]; arr[i] = arr[j]; arr[j] = t; } return arr; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IOPGasPriceOracle} from "../interfaces/IOPGasPriceOracle.sol"; library ChainHelper { address public constant OP_GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F); uint256 public constant OP_MAINNET_CHAIN_ID = 10; uint256 public constant OP_GOERLI_TESTNET_CHAIN_ID = 420; uint256 public constant OP_DEVNET_L1_CHAIN_ID = 900; uint256 public constant OP_DEVNET_L2_CHAIN_ID = 901; uint32 public constant OP_BASIC_FULFILLMENT_L1_GAS_USED = 5016; uint32 public constant OP_FULFILLMENT_GAS_PER_PARTICIPANT = 652; uint256 public constant OP_DIVISOR_DECIMALS = 6; function getBlockTime() public view returns (uint256) { uint256 chainId = block.chainid; if (chainId == OP_MAINNET_CHAIN_ID || chainId == OP_GOERLI_TESTNET_CHAIN_ID || chainId == OP_DEVNET_L2_CHAIN_ID) { return 2; } else if (chainId == OP_DEVNET_L1_CHAIN_ID) { return 3; } return 12; } function getCurrentTxL1GasFees() public view returns (uint256) { uint256 chainId = block.chainid; if (chainId == OP_MAINNET_CHAIN_ID || chainId == OP_GOERLI_TESTNET_CHAIN_ID || chainId == OP_DEVNET_L2_CHAIN_ID) { return IOPGasPriceOracle(OP_GAS_PRICE_ORACLE_ADDR).getL1Fee(msg.data); } return 0; } function getTxL1GasFees(uint256 l1GasUsed) public view returns (uint256) { uint256 chainId = block.chainid; if (chainId == OP_MAINNET_CHAIN_ID || chainId == OP_GOERLI_TESTNET_CHAIN_ID || chainId == OP_DEVNET_L2_CHAIN_ID) { uint256 l1Fee = l1GasUsed * IOPGasPriceOracle(OP_GAS_PRICE_ORACLE_ADDR).l1BaseFee(); uint256 divisor = 10 ** OP_DIVISOR_DECIMALS; uint256 unscaled = l1Fee * IOPGasPriceOracle(OP_GAS_PRICE_ORACLE_ADDR).scalar(); return unscaled / divisor; } return 0; } function getFulfillmentTxL1GasUsed(uint32 groupSize) public view returns (uint256) { uint256 chainId = block.chainid; if (chainId == OP_MAINNET_CHAIN_ID || chainId == OP_GOERLI_TESTNET_CHAIN_ID || chainId == OP_DEVNET_L2_CHAIN_ID) { return OP_BASIC_FULFILLMENT_L1_GAS_USED + groupSize * OP_FULFILLMENT_GAS_PER_PARTICIPANT; } return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://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.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; import "../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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @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] * ``` * 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 Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _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 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _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() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @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 { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @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 IERC1822ProxiableUpgradeable { /** * @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 v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/IERC1967Upgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {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 bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IRequestTypeBase { enum RequestType { Randomness, RandomWords, Shuffling } }
// SPDX-License-Identifier: LGPL 3.0 pragma solidity ^0.8.18; /** * @title Elliptic curve operations on twist points for alt_bn128 * @author ARPA-Network adapted from https://github.com/musalbas/solidity-BN256G2 * @dev Homepage: https://github.com/ARPA-Network/BLS-TSS-Network */ library BN256G2 { uint256 public constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47; uint256 public constant TWISTBX = 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5; uint256 public constant TWISTBY = 0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2; uint256 public constant PTXX = 0; uint256 public constant PTXY = 1; uint256 public constant PTYX = 2; uint256 public constant PTYY = 3; uint256 public constant PTZX = 4; uint256 public constant PTZY = 5; function ecTwistAdd(uint256[4] memory pt1, uint256[4] memory pt2) internal view returns (uint256[4] memory pt) { (uint256 xx, uint256 xy, uint256 yx, uint256 yy) = ecTwistAdd(pt1[0], pt1[1], pt1[2], pt1[3], pt2[0], pt2[1], pt2[2], pt2[3]); pt = [xx, xy, yx, yy]; } /** * @notice Add two twist points * @param pt1xx Coefficient 1 of x on point 1 * @param pt1xy Coefficient 2 of x on point 1 * @param pt1yx Coefficient 1 of y on point 1 * @param pt1yy Coefficient 2 of y on point 1 * @param pt2xx Coefficient 1 of x on point 2 * @param pt2xy Coefficient 2 of x on point 2 * @param pt2yx Coefficient 1 of y on point 2 * @param pt2yy Coefficient 2 of y on point 2 * @return (pt3xx, pt3xy, pt3yx, pt3yy) */ function ecTwistAdd( uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy ) internal view returns (uint256, uint256, uint256, uint256) { if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) { if (!(pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0)) { assert(isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy)); } return (pt2xx, pt2xy, pt2yx, pt2yy); } else if (pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0) { assert(isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy)); return (pt1xx, pt1xy, pt1yx, pt1yy); } assert(isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy)); assert(isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy)); uint256[6] memory pt1 = [pt1xx, pt1xy, pt1yx, pt1yy, 1, 0]; uint256[6] memory pt2 = [pt2xx, pt2xy, pt2yx, pt2yy, 1, 0]; uint256[6] memory pt3 = ecTwistAddJacobian(pt1, pt2); return fromJacobian(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]); } function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) { return addmod(a, n - b, n); } function fq2Mul(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (uint256, uint256) { return ( submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS), addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS) ); } function fq2Muc(uint256 xx, uint256 xy, uint256 c) internal pure returns (uint256, uint256) { return (mulmod(xx, c, FIELD_MODULUS), mulmod(xy, c, FIELD_MODULUS)); } function fq2Sub(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (uint256 rx, uint256 ry) { return (submod(xx, yx, FIELD_MODULUS), submod(xy, yy, FIELD_MODULUS)); } function fq2Inv(uint256 x, uint256 y) internal view returns (uint256, uint256) { uint256 inv = modInv(addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS), FIELD_MODULUS); return (mulmod(x, inv, FIELD_MODULUS), FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS)); } function isOnCurve(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (bool) { uint256 yyx; uint256 yyy; uint256 xxxx; uint256 xxxy; (yyx, yyy) = fq2Mul(yx, yy, yx, yy); (xxxx, xxxy) = fq2Mul(xx, xy, xx, xy); (xxxx, xxxy) = fq2Mul(xxxx, xxxy, xx, xy); (yyx, yyy) = fq2Sub(yyx, yyy, xxxx, xxxy); (yyx, yyy) = fq2Sub(yyx, yyy, TWISTBX, TWISTBY); return yyx == 0 && yyy == 0; } function modInv(uint256 a, uint256 n) internal view returns (uint256 result) { bool success; // solhint-disable-next-line no-inline-assembly assembly { let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), a) mstore(add(freemem, 0x80), sub(n, 2)) mstore(add(freemem, 0xA0), n) success := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) result := mload(freemem) } // solhint-disable-next-line reason-string require(success); } function fromJacobian(uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt1zx, uint256 pt1zy) internal view returns (uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy) { uint256 invzx; uint256 invzy; (invzx, invzy) = fq2Inv(pt1zx, pt1zy); (pt2xx, pt2xy) = fq2Mul(pt1xx, pt1xy, invzx, invzy); (pt2yx, pt2yy) = fq2Mul(pt1yx, pt1yy, invzx, invzy); } function ecTwistAddJacobian(uint256[6] memory pt1, uint256[6] memory pt2) public pure returns (uint256[6] memory pt3) { if (pt1[4] == 0 && pt1[5] == 0) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (pt2[0], pt2[1], pt2[2], pt2[3], pt2[4], pt2[5]); return pt3; } else if (pt2[4] == 0 && pt2[5] == 0) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5]); return pt3; } (pt2[2], pt2[3]) = fq2Mul(pt2[2], pt2[3], pt1[4], pt1[5]); // U1 = y2 * z1 (pt3[PTYX], pt3[PTYY]) = fq2Mul(pt1[2], pt1[3], pt2[4], pt2[5]); // U2 = y1 * z2 (pt2[0], pt2[1]) = fq2Mul(pt2[0], pt2[1], pt1[4], pt1[5]); // V1 = x2 * z1 (pt3[PTZX], pt3[PTZY]) = fq2Mul(pt1[0], pt1[1], pt2[4], pt2[5]); // V2 = x1 * z2 if (pt2[0] == pt3[PTZX] && pt2[1] == pt3[PTZY]) { if (pt2[2] == pt3[PTYX] && pt2[3] == pt3[PTYY]) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = ecTwistDoubleJacobian(pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5]); return pt3; } (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (1, 0, 1, 0, 0, 0); return pt3; } (pt2[4], pt2[5]) = fq2Mul(pt1[4], pt1[5], pt2[4], pt2[5]); // W = z1 * z2 (pt1[0], pt1[1]) = fq2Sub(pt2[2], pt2[3], pt3[PTYX], pt3[PTYY]); // U = U1 - U2 (pt1[2], pt1[3]) = fq2Sub(pt2[0], pt2[1], pt3[PTZX], pt3[PTZY]); // V = V1 - V2 (pt1[4], pt1[5]) = fq2Mul(pt1[2], pt1[3], pt1[2], pt1[3]); // V_squared = V * V (pt2[2], pt2[3]) = fq2Mul(pt1[4], pt1[5], pt3[PTZX], pt3[PTZY]); // V_squared_times_V2 = V_squared * V2 (pt1[4], pt1[5]) = fq2Mul(pt1[4], pt1[5], pt1[2], pt1[3]); // V_cubed = V * V_squared (pt3[PTZX], pt3[PTZY]) = fq2Mul(pt1[4], pt1[5], pt2[4], pt2[5]); // newz = V_cubed * W (pt2[0], pt2[1]) = fq2Mul(pt1[0], pt1[1], pt1[0], pt1[1]); // U * U (pt2[0], pt2[1]) = fq2Mul(pt2[0], pt2[1], pt2[4], pt2[5]); // U * U * W (pt2[0], pt2[1]) = fq2Sub(pt2[0], pt2[1], pt1[4], pt1[5]); // U * U * W - V_cubed (pt2[4], pt2[5]) = fq2Muc(pt2[2], pt2[3], 2); // 2 * V_squared_times_V2 (pt2[0], pt2[1]) = fq2Sub(pt2[0], pt2[1], pt2[4], pt2[5]); // A = U * U * W - V_cubed - 2 * V_squared_times_V2 (pt3[PTXX], pt3[PTXY]) = fq2Mul(pt1[2], pt1[3], pt2[0], pt2[1]); // newx = V * A (pt1[2], pt1[3]) = fq2Sub(pt2[2], pt2[3], pt2[0], pt2[1]); // V_squared_times_V2 - A (pt1[2], pt1[3]) = fq2Mul(pt1[0], pt1[1], pt1[2], pt1[3]); // U * (V_squared_times_V2 - A) (pt1[0], pt1[1]) = fq2Mul(pt1[4], pt1[5], pt3[PTYX], pt3[PTYY]); // V_cubed * U2 (pt3[PTYX], pt3[PTYY]) = fq2Sub(pt1[2], pt1[3], pt1[0], pt1[1]); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2 } function ecTwistDoubleJacobian( uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt1zx, uint256 pt1zy ) public pure returns (uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy, uint256 pt2zx, uint256 pt2zy) { (pt2xx, pt2xy) = fq2Muc(pt1xx, pt1xy, 3); // 3 * x (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x (pt1zx, pt1zy) = fq2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z (pt2yx, pt2yy) = fq2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y (pt2yx, pt2yy) = fq2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S (pt1xx, pt1xy) = fq2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W (pt2zx, pt2zy) = fq2Muc(pt2yx, pt2yy, 8); // 8 * B (pt1xx, pt1xy) = fq2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B (pt2zx, pt2zy) = fq2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S (pt2yx, pt2yy) = fq2Muc(pt2yx, pt2yy, 4); // 4 * B (pt2yx, pt2yy) = fq2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H (pt2yx, pt2yy) = fq2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H) (pt2xx, pt2xy) = fq2Muc(pt1yx, pt1yy, 8); // 8 * y (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared (pt2yx, pt2yy) = fq2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared (pt2xx, pt2xy) = fq2Muc(pt1xx, pt1xy, 2); // 2 * H (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S (pt2zx, pt2zy) = fq2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared (pt2zx, pt2zy) = fq2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IOPGasPriceOracle { /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input /// transaction, the current L1 base fee, and the various dynamic parameters. /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. /// @return L1 fee that should be paid for the tx function getL1Fee(bytes memory _data) external view returns (uint256); /// @notice Retrieves the current fee scalar. /// @return Current fee scalar. function scalar() external view returns (uint256); /// @notice Retrieves the latest known L1 base fee. /// @return Latest known L1 base fee. function l1BaseFee() external view returns (uint256); }
// 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 AddressUpgradeable { /** * @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 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 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.9._ */ interface IERC1967Upgradeable { /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @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: * ``` * 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(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 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 } } }
{ "remappings": [ "Randcast-User-Contract/=lib/Randcast-User-Contract/contracts/", "Staking-v0.1/=lib/Staking-v0.1/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 300 }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": { "src/libraries/BLS.sol": { "BLS": "0x34E6885e0e9BBEA0Bae36d00D4D9B4ED873f2cA8" }, "src/libraries/ChainHelper.sol": { "ChainHelper": "0x8fFe9b19591b031c7b76a27D1B356eD0A8441B80" } } }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AtLeastOneRequestIsRequired","type":"error"},{"inputs":[],"name":"EmptyPartialSignatures","type":"error"},{"inputs":[{"internalType":"uint32","name":"have","type":"uint32"},{"internalType":"uint32","name":"want","type":"uint32"}],"name":"GasLimitTooBig","type":"error"},{"inputs":[{"internalType":"uint256","name":"groupIndex","type":"uint256"}],"name":"GroupNotExist","type":"error"},{"inputs":[],"name":"IdenticalSubscription","type":"error"},{"inputs":[],"name":"IncorrectCommitment","type":"error"},{"inputs":[],"name":"InsufficientBalanceWhenFulfill","type":"error"},{"inputs":[],"name":"InsufficientBalanceWhenRequest","type":"error"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"address","name":"consumer","type":"address"}],"name":"InvalidConsumer","type":"error"},{"inputs":[],"name":"InvalidPartialSignatureFormat","type":"error"},{"inputs":[],"name":"InvalidPartialSignatures","type":"error"},{"inputs":[],"name":"InvalidRequestByEOA","type":"error"},{"inputs":[{"internalType":"uint16","name":"have","type":"uint16"},{"internalType":"uint16","name":"min","type":"uint16"},{"internalType":"uint16","name":"max","type":"uint16"}],"name":"InvalidRequestConfirmations","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureFormat","type":"error"},{"inputs":[],"name":"InvalidSubscription","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"MustBeSubOwner","type":"error"},{"inputs":[],"name":"NoAvailableGroups","type":"error"},{"inputs":[],"name":"NoCorrespondingRequest","type":"error"},{"inputs":[],"name":"NotFromCommitter","type":"error"},{"inputs":[],"name":"PendingRequestExists","type":"error"},{"inputs":[],"name":"Reentrant","type":"error"},{"inputs":[],"name":"ReferralPromotionDisabled","type":"error"},{"inputs":[],"name":"RequestNotExpired","type":"error"},{"inputs":[],"name":"SenderNotController","type":"error"},{"inputs":[],"name":"SubscriptionAlreadyHasReferral","type":"error"},{"inputs":[],"name":"TaskStillExclusive","type":"error"},{"inputs":[],"name":"TaskStillWithinRequestConfirmations","type":"error"},{"inputs":[],"name":"TooManyConsumers","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"minimumRequestConfirmations","type":"uint16"},{"indexed":false,"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"gasAfterPaymentCalculation","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"gasExceptCallback","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"signatureTaskExclusiveWindow","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerSignature","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"committerRewardPerSignature","type":"uint256"}],"name":"AdapterConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier1","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier2","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier3","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier4","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier5","type":"uint32"},{"internalType":"uint24","name":"reqsForTier2","type":"uint24"},{"internalType":"uint24","name":"reqsForTier3","type":"uint24"},{"internalType":"uint24","name":"reqsForTier4","type":"uint24"},{"internalType":"uint24","name":"reqsForTier5","type":"uint24"}],"indexed":false,"internalType":"struct IAdapterOwner.FeeConfig","name":"flatFeeConfig","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"flatFeePromotionGlobalPercentage","type":"uint16"},{"indexed":false,"internalType":"bool","name":"isFlatFeePromotionEnabledPermanently","type":"bool"},{"indexed":false,"internalType":"uint256","name":"flatFeePromotionStartTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"flatFeePromotionEndTimestamp","type":"uint256"}],"name":"FlatFeeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"}],"name":"OvertimeRequestCanceled","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":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":true,"internalType":"uint32","name":"groupIndex","type":"uint32"},{"indexed":false,"internalType":"enum IRequestTypeBase.RequestType","name":"requestType","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"seed","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"indexed":false,"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"callbackMaxGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"estimatedPayment","type":"uint256"}],"name":"RandomnessRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"groupIndex","type":"uint32"},{"indexed":true,"internalType":"address","name":"committer","type":"address"},{"indexed":false,"internalType":"address[]","name":"participantMembers","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"randommness","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"flatFee","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"RandomnessRequestResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isReferralEnabled","type":"bool"},{"indexed":false,"internalType":"uint16","name":"freeRequestCountForReferrer","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"freeRequestCountForReferee","type":"uint16"}],"name":"ReferralConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SubscriptionCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":false,"internalType":"address","name":"consumer","type":"address"}],"name":"SubscriptionConsumerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":false,"internalType":"address","name":"consumer","type":"address"}],"name":"SubscriptionConsumerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"SubscriptionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"oldBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"SubscriptionFunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"subId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"referralSubId","type":"uint64"}],"name":"SubscriptionReferralSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_MINIMUM_THRESHOLD","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CONSUMERS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUEST_CONFIRMATIONS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RANDOMNESS_REWARD_GAS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFICATION_GAS_OVER_MINIMUM_THRESHOLD","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"address","name":"consumer","type":"address"}],"name":"addConsumer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"components":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"uint32","name":"groupIndex","type":"uint32"},{"internalType":"enum IRequestTypeBase.RequestType","name":"requestType","type":"uint8"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint256","name":"callbackMaxGasPrice","type":"uint256"},{"internalType":"uint256","name":"blockNum","type":"uint256"}],"internalType":"struct IAdapter.RequestDetail","name":"requestDetail","type":"tuple"}],"name":"cancelOvertimeRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"address","name":"to","type":"address"}],"name":"cancelSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createSubscription","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint32","name":"gasExceptCallback","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPM","type":"uint32"},{"internalType":"uint256","name":"weiPerUnitGas","type":"uint256"},{"internalType":"uint32","name":"groupSize","type":"uint32"}],"name":"estimatePaymentAmountInETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"groupIndex","type":"uint32"},{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"signature","type":"uint256"},{"components":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"uint32","name":"groupIndex","type":"uint32"},{"internalType":"enum IRequestTypeBase.RequestType","name":"requestType","type":"uint8"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint256","name":"callbackMaxGasPrice","type":"uint256"},{"internalType":"uint256","name":"blockNum","type":"uint256"}],"internalType":"struct IAdapter.RequestDetail","name":"requestDetail","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"partialSignature","type":"uint256"}],"internalType":"struct IAdapter.PartialSignature[]","name":"partialSignatures","type":"tuple[]"}],"name":"fulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"}],"name":"fundSubscription","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAdapterConfig","outputs":[{"internalType":"uint16","name":"minimumRequestConfirmations","type":"uint16"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"uint32","name":"gasAfterPaymentCalculation","type":"uint32"},{"internalType":"uint32","name":"gasExceptCallback","type":"uint32"},{"internalType":"uint256","name":"signatureTaskExclusiveWindow","type":"uint256"},{"internalType":"uint256","name":"rewardPerSignature","type":"uint256"},{"internalType":"uint256","name":"committerRewardPerSignature","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCumulativeData","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentSubId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"reqCount","type":"uint64"}],"name":"getFeeTier","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlatFeeConfig","outputs":[{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPMTier1","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPMTier2","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPMTier3","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPMTier4","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPMTier5","type":"uint32"},{"internalType":"uint24","name":"reqsForTier2","type":"uint24"},{"internalType":"uint24","name":"reqsForTier3","type":"uint24"},{"internalType":"uint24","name":"reqsForTier4","type":"uint24"},{"internalType":"uint24","name":"reqsForTier5","type":"uint24"},{"internalType":"uint16","name":"flatFeePromotionGlobalPercentage","type":"uint16"},{"internalType":"bool","name":"isFlatFeePromotionEnabledPermanently","type":"bool"},{"internalType":"uint256","name":"flatFeePromotionStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"flatFeePromotionEndTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastAssignedGroupIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRandomness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"consumer","type":"address"}],"name":"getLastSubscription","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"getPendingRequestCommitment","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRandomnessCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReferralConfig","outputs":[{"internalType":"bool","name":"isReferralEnabled","type":"bool"},{"internalType":"uint16","name":"freeRequestCountForReferrer","type":"uint16"},{"internalType":"uint16","name":"freeRequestCountForReferee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"}],"name":"getSubscription","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[]","name":"consumers","type":"address[]"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"inflightCost","type":"uint256"},{"internalType":"uint64","name":"reqCount","type":"uint64"},{"internalType":"uint64","name":"freeRequestCount","type":"uint64"},{"internalType":"uint64","name":"referralSubId","type":"uint64"},{"internalType":"uint64","name":"reqCountInCurrentPeriod","type":"uint64"},{"internalType":"uint256","name":"lastRequestTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"nodeWithdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"}],"name":"ownerCancelSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"address","name":"consumer","type":"address"}],"name":"removeConsumer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum IRequestTypeBase.RequestType","name":"requestType","type":"uint8"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint256","name":"callbackMaxGasPrice","type":"uint256"}],"internalType":"struct IAdapter.RandomnessRequestParams","name":"params","type":"tuple"}],"name":"requestRandomness","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"minimumRequestConfirmations","type":"uint16"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"uint32","name":"gasAfterPaymentCalculation","type":"uint32"},{"internalType":"uint32","name":"gasExceptCallback","type":"uint32"},{"internalType":"uint256","name":"signatureTaskExclusiveWindow","type":"uint256"},{"internalType":"uint256","name":"rewardPerSignature","type":"uint256"},{"internalType":"uint256","name":"committerRewardPerSignature","type":"uint256"}],"name":"setAdapterConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier1","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier2","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier3","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier4","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeEthPPMTier5","type":"uint32"},{"internalType":"uint24","name":"reqsForTier2","type":"uint24"},{"internalType":"uint24","name":"reqsForTier3","type":"uint24"},{"internalType":"uint24","name":"reqsForTier4","type":"uint24"},{"internalType":"uint24","name":"reqsForTier5","type":"uint24"}],"internalType":"struct IAdapterOwner.FeeConfig","name":"flatFeeConfig","type":"tuple"},{"internalType":"uint16","name":"flatFeePromotionGlobalPercentage","type":"uint16"},{"internalType":"bool","name":"isFlatFeePromotionEnabledPermanently","type":"bool"},{"internalType":"uint256","name":"flatFeePromotionStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"flatFeePromotionEndTimestamp","type":"uint256"}],"name":"setFlatFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"subIds","type":"uint64[]"},{"internalType":"uint64[]","name":"freeRequestCounts","type":"uint64[]"}],"name":"setFreeRequestCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"uint64","name":"referralSubId","type":"uint64"}],"name":"setReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isReferralEnabled","type":"bool"},{"internalType":"uint16","name":"freeRequestCountForReferrer","type":"uint16"},{"internalType":"uint16","name":"freeRequestCountForReferee","type":"uint16"}],"name":"setReferralConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615f306200012060003960008181610af701528181610b4001528181610bdc01528181610c1c0152610caf0152615f306000f3fe6080604052600436106102565760003560e01c806391a6fe7711610149578063c725a833116100c6578063dcdb7b881161008a578063f2fde38b11610064578063f2fde38b1461090a578063f362ca611461092a578063f4cc97fc1461094a57600080fd5b8063dcdb7b8814610721578063dfaba79414610889578063ef6f42731461089c57600080fd5b8063c725a83314610670578063caba5284146106a1578063d2f9f9a7146106c1578063d7ae1d30146106e1578063d89f241f1461070157600080fd5b8063a39402d71161010d578063a39402d7146105d1578063a47c7696146105f1578063a4c343f214610626578063aa81d59a1461063b578063c4d66de81461065057600080fd5b806391a6fe7714610541578063931d92041461055c5780639f87fad71461057c578063a141bbd81461059c578063a21a23e4146105bc57600080fd5b806352d1902d116101d75780637341c10c1161019b5780637341c10c1461048057806376a911bc146104a05780638166d459146104e2578063877d38bb1461050d5780638da5cb5b1461052357600080fd5b806352d1902d1461040c578063636021741461042157806364d51a2a14610436578063715018a61461044b57806371b7ca051461046057600080fd5b806315c48b841161021e57806315c48b841461032f5780631e58a872146103575780633018205f146103a75780633659cfe6146103d95780634f1ef286146103f957600080fd5b806302bcc5b61461025b578063056e5ede1461027d57806306bfa6371461029d5780630ad98f6a146102d45780631565034c146102f4575b600080fd5b34801561026757600080fd5b5061027b6102763660046147c2565b61096a565b005b34801561028957600080fd5b5061027b61029836600461496a565b6109e1565b3480156102a957600080fd5b5060d7546001600160401b03165b6040516001600160401b0390911681526020015b60405180910390f35b3480156102e057600080fd5b5061027b6102ef3660046149ed565b610a8c565b34801561030057600080fd5b5061032161030f366004614a19565b600090815260d4602052604090205490565b6040519081526020016102cb565b34801561033b57600080fd5b5061034460c881565b60405161ffff90911681526020016102cb565b34801561036357600080fd5b5061038560d85460ff81169161ffff6101008304811692630100000090041690565b60408051931515845261ffff92831660208501529116908201526060016102cb565b3480156103b357600080fd5b5060c9546001600160a01b03165b6040516001600160a01b0390911681526020016102cb565b3480156103e557600080fd5b5061027b6103f4366004614a32565b610aed565b61027b610407366004614abe565b610bd2565b34801561041857600080fd5b50610321610ca2565b34801561042d57600080fd5b5060cf54610321565b34801561044257600080fd5b50610344606481565b34801561045757600080fd5b5061027b610d55565b34801561046c57600080fd5b5061027b61047b366004614b32565b610d69565b34801561048c57600080fd5b5061027b61049b366004614ba7565b610ebd565b3480156104ac57600080fd5b506102b76104bb366004614a32565b6001600160a01b0316600090815260d560205260409020600101546001600160401b031690565b3480156104ee57600080fd5b506104f861232881565b60405163ffffffff90911681526020016102cb565b34801561051957600080fd5b506104f861c35081565b34801561052f57600080fd5b506097546001600160a01b03166103c1565b34801561054d57600080fd5b5060cd5463ffffffff16610321565b34801561056857600080fd5b5061027b610577366004614bde565b611080565b34801561058857600080fd5b5061027b610597366004614ba7565b61135d565b3480156105a857600080fd5b506103216105b7366004614c11565b611693565b3480156105c857600080fd5b506102b76117e6565b3480156105dd57600080fd5b506103216105ec366004614c79565b6118df565b3480156105fd57600080fd5b5061061161060c3660046147c2565b611cfd565b6040516102cb99989796959493929190614cf7565b34801561063257600080fd5b5060ce54610321565b34801561064757600080fd5b506104f8600381565b34801561065c57600080fd5b5061027b61066b366004614a32565b611e1d565b34801561067c57600080fd5b5060ca5460cb5460cc54604080519384526020840192909252908201526060016102cb565b3480156106ad57600080fd5b5061027b6106bc366004614d7a565b611f49565b3480156106cd57600080fd5b506104f86106dc3660046147c2565b612397565b3480156106ed57600080fd5b5061027b6106fc366004614ba7565b612514565b34801561070d57600080fd5b5061027b61071c366004614e38565b612620565b34801561072d57600080fd5b50604080516101208101825260d95463ffffffff8082168084526401000000008304821660208501819052600160401b84048316958501869052600160601b8404831660608601819052600160801b85049093166080860181905262ffffff600160a01b8604811660a08801819052600160b81b8704821660c08901819052600160d01b8804831660e08a01819052600160e81b90980490921661010090980188905260da5460db5460dc54969a95999598949692959394939261ffff83169260ff620100009091041691906040516102cb9d9c9b9a9998979695949392919063ffffffff9d8e1681529b8d1660208d0152998c1660408c0152978b1660608b015295909916608089015262ffffff93841660a089015291831660c0880152821660e08701521661010085015261ffff949094166101208401529215156101408301526101608201929092526101808101919091526101a00190565b61027b6108973660046147c2565b612971565b3480156108a857600080fd5b5060d05460d15460d25460d3546040805161ffff8616815263ffffffff62010000870481166020830152600160381b8704811692820192909252600160581b909504166060850152608084019290925260a083015260c082015260e0016102cb565b34801561091657600080fd5b5061027b610925366004614a32565b612a5d565b34801561093657600080fd5b5061027b610945366004614e8d565b612ad3565b34801561095657600080fd5b5061027b610965366004614ee5565b612b6d565b610972612da7565b6001600160401b038116600090815260d660205260409020546001600160a01b03166109b157604051630fb532db60e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260409020546109de9082906001600160a01b0316612e01565b50565b6109e9612da7565b60005b8251811015610a8757818181518110610a0757610a07614fe7565b602002602001015160d66000858481518110610a2557610a25614fe7565b60200260200101516001600160401b03166001600160401b0316815260200190815260200160002060060160086101000a8154816001600160401b0302191690836001600160401b031602179055508080610a7f90615013565b9150506109ec565b505050565b60c9546001600160a01b03163314610ab757604051630f5caa3360e41b815260040160405180910390fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610a87573d6000803e3d6000fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b3e5760405162461bcd60e51b8152600401610b359061502c565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b87600080516020615eb4833981519152546001600160a01b031690565b6001600160a01b031614610bad5760405162461bcd60e51b8152600401610b3590615078565b610bb681612ed3565b604080516000808252602082019092526109de91839190612edb565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c1a5760405162461bcd60e51b8152600401610b359061502c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c63600080516020615eb4833981519152546001600160a01b031690565b6001600160a01b031614610c895760405162461bcd60e51b8152600401610b3590615078565b610c9282612ed3565b610c9e82826001612edb565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d425760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610b35565b50600080516020615eb483398151915290565b610d5d612da7565b610d676000613046565b565b610d71612da7565b60c861ffff88161115610dab5760405163539c34bb60e11b815261ffff881660048201819052602482015260c86044820152606401610b35565b604080516101008101825261ffff891680825263ffffffff89811660208085018290526000858701528a83166060808701829052938b16608080880182905260a08089018d905260c0808a018d905260e0998a018c905260d0805465ffffffffffff19168a17620100008902176effffffffffffffffff0000000000001916600160381b87026effffffff0000000000000000000000191617600160581b860217905560d18e905560d28d905560d38c90558a519889529488019590955297860191909152928401929092529382018790529281018590529182018390527fefeb3292465cf72a302efdd83695ad560a2828353a1e018844e9abd19a642037910160405180910390a150505050505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b031680610eff57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614610f3357604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff1615610f5e5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038416600090815260d6602052604090206002015460631901610f9b576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b038316600090815260d5602090815260408083206001600160401b038089168552925282205416900361107a576001600160a01b038316600081815260d5602090815260408083206001600160401b0389168085528184528285208054600167ffffffffffffffff1991821681179092559281018054909316821790925560d68452828520600201805492830181558552938390200180546001600160a01b031916851790555192835290917f43dc749a04ac8fb825cbd514f7c0e13f13bc6f2ee66043b76629d51776cff8e0910160405180910390a25b50505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b0316806110c257604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146110f657604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156111215760405163769dd35360e11b815260040160405180910390fd5b60d85460ff1661114457604051636dac270160e01b815260040160405180910390fd5b6001600160401b03808416600090815260d660205260408082205492871682529020546001600160a01b039182169116036111925760405163027f035560e51b815260040160405180910390fd5b6001600160401b03808516600090815260d66020526040902060060154600160801b900416156111d55760405163cae26ee160e01b815260040160405180910390fd5b6001600160401b03808516600090815260d6602052604090206006015416158061121a57506001600160401b03808416600090815260d6602052604090206006015416155b156112385760405163a760a23760e01b815260040160405180910390fd5b60d8546001600160401b03848116600090815260d660205260409020600601805461010090930461ffff1692909160089161127c918591600160401b9004166150c4565b82546101009290920a6001600160401b0381810219909316918316021790915560d854868216600090815260d6602052604090206006018054630100000090920461ffff169350916008916112da918591600160401b9004166150c4565b82546101009290920a6001600160401b03818102199093169183160217909155858116600081815260d66020526040808220600601805467ffffffffffffffff60801b1916600160801b958a169586021790555192935090917fb661d46b53034f62a6c7d50df2a5e055fab98889aaf62f8c618e457edd96c6889190a350505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b03168061139f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146113d357604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156113fe5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038416600090815260d660205260409020600401541561143857604051631685ecdd60e31b815260040160405180910390fd5b6001600160401b038416600090815260d660209081526040808320600201805482518185028101850190935280835291929091908301828280156114a557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611487575b5050505050905080516000036114e857604051637800cff360e11b81526001600160401b03861660048201526001600160a01b0385166024820152604401610b35565b60005b815181101561165f57846001600160a01b031682828151811061151057611510614fe7565b60200260200101516001600160a01b03160361164d57816001835161153591906150eb565b8151811061154557611545614fe7565b602002602001015160d66000886001600160401b03166001600160401b03168152602001908152602001600020600201828154811061158657611586614fe7565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394909416939093179092556001600160401b038816815260d6909152604090206002018054806115da576115da6150fe565b6000828152602090819020600019908301810180546001600160a01b03191690559091019091556040516001600160a01b03871681526001600160401b038816917f182bff9831466789164ca77075fffd84916d35a8180ba73c27e45634549b445b910160405180910390a2505061107a565b8061165781615013565b9150506114eb565b50604051637800cff360e11b81526001600160401b03861660048201526001600160a01b0385166024820152604401610b35565b60405163745e0dcf60e01b815263ffffffff821660048201526000908190600290738ffe9b19591b031c7b76a27d1b356ed0a8441b8090638e3976f690829063745e0dcf90602401602060405180830381865af41580156116f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171c9190615114565b6040518263ffffffff1660e01b815260040161173a91815260200190565b602060405180830381865af4158015611757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177b9190615114565b61178690600361512d565b611790919061515a565b905060008161179f898961516e565b6117af9063ffffffff168761512d565b6117b9919061518b565b90506117d063ffffffff871664e8d4a5100061512d565b6117da908261518b565b98975050505050505050565b60d054600090600160301b900460ff16156118145760405163769dd35360e11b815260040160405180910390fd5b60d780546001600160401b031690600061182d8361519e565b82546001600160401b039182166101009390930a92830292820219169190911790915560d780548216600090815260d6602052604080822080546001600160a01b0319163390811790915583548516835281832060060180546fffffffffffffffff00000000000000001916600160401b17905592549051929450909216917f464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf91a35060d7546001600160401b031690565b60d054600090600160301b900460ff161561190d5760405163769dd35360e11b815260040160405180910390fd5b6000611918836151d3565b905032330361193a57604051638a3150e760e01b815260040160405180910390fd5b6040808201516001600160401b0316600090815260d66020522080546001600160a01b031661197c57604051630fb532db60e11b815260040160405180910390fd5b33600090815260d560209081526040808320858201516001600160401b03908116855292528220541690036119db576040808301519051637800cff360e11b81526001600160401b039091166004820152336024820152604401610b35565b60d054608083015161ffff91821691161080611a03575060c861ffff16826080015161ffff16115b15611a3e57608082015160d05460405163539c34bb60e11b815261ffff92831660048201529116602482015260c86044820152606401610b35565b60d05460a083015163ffffffff62010000909204821691161115611a955760a082015160d054604051637aebf00f60e11b815263ffffffff9283166004820152620100009091049091166024820152604401610b35565b611a9d613098565b60cd805463ffffffff191663ffffffff9290921691909117905560608201516040808401805133600081815260d5602090815285822094516001600160401b039081168352949052938420549394611af794909316613209565b6040848101805133600090815260d560209081528482206001808201805467ffffffffffffffff19166001600160401b03968716179055945184168352905292832080549495509193919291611b4f918591166150c4565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506000611b7e82613268565b60c95460cd5460405163f49e0ba960e01b815263ffffffff90911660048201529192506000916001600160a01b039091169063f49e0ba9906024016040805180830381865afa158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615271565b9150506000611c138584848960a001518a60c0015161329a565b60408088015160cd5489516020808c015160808d015160a08e015160c08f01519751989950611c59988c9863ffffffff90971696939433948f949392909143910161531d565b60408051601f198184030181528282528051602091820120600087815260d483528390205560cd54918901518951918a015160808b015160a08c015160c08d015163ffffffff909616966001600160401b03909416958a957fd26299589dd9197a8dc30a0fa17b0fe7dd432bc3441aa5f5631ea1e14c1af74495611ce7959194919333938f93928d906153a8565b60405180910390a450909450505050505b919050565b6001600160401b038116600090815260d660205260408120805460609183918291829182918291829182916001600160a01b0316611d4e57604051630fb532db60e11b815260040160405180910390fd5b80546003820154600483015460068401546007850154600286018054604080516020808402820181019092528281526001600160a01b0390981697929695946001600160401b0380821695600160401b8304821695600160801b8404831695600160c01b9094049092169390928a91830182828015611df657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611dd8575b50505050509750995099509950995099509950995099509950509193959799909294969850565b600054610100900460ff1615808015611e3d5750600054600160ff909116105b80611e575750303b158015611e57575060005460ff166001145b611eba5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b35565b6000805460ff191660011790558015611edd576000805461ff0019166101001790555b60c980546001600160a01b0319166001600160a01b038416179055611f00613420565b8015610c9e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60d054600160301b900460ff1615611f745760405163769dd35360e11b815260040160405180910390fd5b60005a600087815260d46020526040812054919250819003611fa957604051631b44092560e11b815260040160405180910390fd5b86611fb760208701876147c2565b611fc7604088016020890161540f565b611fd76060890160408a0161542c565b611fe460608a018a615447565b611ff460a08c0160808d01614a32565b60a08c013561200960e08e0160c08f01615494565b8d60e001602081019061201c919061540f565b8e61010001358f61012001356040516020016120439c9b9a999897969594939291906154af565b6040516020818303038152906040528051906020012081146120785760405163354a450b60e21b815260040160405180910390fd5b61208860e0860160c08701615494565b61209b9061ffff1661012087013561518b565b4310156120bb5760405163619a4abd60e01b815260040160405180910390fd5b6120cb604086016020870161540f565b63ffffffff168863ffffffff16141580156120f7575060d1546120f39061012087013561518b565b4311155b15612115576040516378373bbd60e11b815260040160405180910390fd5b60c960009054906101000a90046001600160a01b03166001600160a01b03166306545a936040518163ffffffff1660e01b8152600401602060405180830381865afa158015612168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218c9190615114565b8863ffffffff16106121b957604051637f6efcb560e11b815263ffffffff89166004820152602401610b35565b60006122298963ffffffff168760a001358861012001358a8989808060200260200160405190810160405280939291908181526020016000905b8282101561221f5761221060408302860136819003810190615557565b815260200190600101906121f3565b505050505061344f565b600089815260d46020908152604080832083905580518083018c9052815180820384018152908201909152805191012060cf805493945090926001929061227190849061518b565b909155505060ce81905560c9546040516379ef840160e11b8152600481018390526001600160a01b039091169063f3df080290602401600060405180830381600087803b1580156122c157600080fd5b505af11580156122d5573d6000803e3d6000fd5b5050505060006122ef8a838a6122ea90615589565b613b3a565b905060008061232860d68261230760208e018e6147c2565b6001600160401b0316815260208101919091526040016000208d8a8a613dd5565b9150915061233785838361408e565b336001600160a01b03168d63ffffffff168d7f6fc1bcb4bd7d5fdf4017f746304b61ae4472496256e906c6bb44682aa2c9a6d8888887878a604051612380959493929190615656565b60405180910390a450505050505050505050505050565b604080516101208101825260d95463ffffffff8082168352640100000000820481166020840152600160401b8204811693830193909352600160601b810483166060830152600160801b8104909216608082015262ffffff600160a01b8304811660a08301819052600160b81b8404821660c0840152600160d01b8404821660e0840152600160e81b909304166101008201526000916001600160401b03841611612443575192915050565b826001600160401b03168160a0015162ffffff1610801561247657508060c0015162ffffff16836001600160401b031611155b15612485576020015192915050565b826001600160401b03168160c0015162ffffff161080156124b857508060e0015162ffffff16836001600160401b031611155b156124c7576040015192915050565b826001600160401b03168160e0015162ffffff161080156124fb575080610100015162ffffff16836001600160401b031611155b1561250a576060015192915050565b6080015192915050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b03168061255657604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b0382161461258a57604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156125b55760405163769dd35360e11b815260040160405180910390fd5b6001600160a01b0383166125dc5760405163f6b2911f60e01b815260040160405180910390fd5b6001600160401b038416600090815260d660205260409020600401541561261657604051631685ecdd60e31b815260040160405180910390fd5b61107a8484612e01565b61262d60208201826147c2565b6001600160401b038116600090815260d660205260409020546001600160a01b03168061266d57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146126a157604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b600084815260d4602052604081205490036126cf57604051631b44092560e11b815260040160405180910390fd5b836126dd60208501856147c2565b6126ed604086016020870161540f565b6126fd606087016040880161542c565b61270a6060880188615447565b61271a60a08a0160808b01614a32565b60a08a013561272f60e08c0160c08d01615494565b6127406101008d0160e08e0161540f565b8c61010001358d61012001356040516020016127679c9b9a999897969594939291906154af565b60408051601f198184030181529181528151602092830120600087815260d4909352912054146127aa5760405163354a450b60e21b815260040160405180910390fd5b6000738ffe9b19591b031c7b76a27d1b356ed0a8441b806387ceff096040518163ffffffff1660e01b8152600401602060405180830381865af41580156127f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128199190615114565b612826906201518061515a565b90506128378161012086013561518b565b43101561285757604051636c804b5d60e01b815260040160405180910390fd5b600085815260d460209081526040822082905560d6919061287a908701876147c2565b6001600160401b03168152602080820192909252604090810160009081208882526005018352908120549160d691906128b5908801886147c2565b6001600160401b03166001600160401b0316815260200190815260200160002060040160008282546128e791906150eb565b9091555060d6905060006128fe60208701876147c2565b6001600160401b0316815260208082019290925260409081016000908120888252600501835290812055612934908501856147c2565b6001600160401b0316857fc1cf1d318384ee8dee53eed48bbf121b2b14fa61e9da5fd2f597dfbee4e5c2e660405160405180910390a35050505050565b60d054600160301b900460ff161561299c5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260409020546001600160a01b03166129db57604051630fb532db60e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260408120600301805491349190612a06838561518b565b90915550506001600160401b0382167fd39ec07f4e209f627a4c427971473820dc129761ba28de8906bd56f57101d4f882612a41348261518b565b6040805192835260208301919091520160405180910390a25050565b612a65612da7565b6001600160a01b038116612aca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b35565b6109de81613046565b612adb612da7565b604080516060808201835285151580835261ffff868116602080860182905291871694860185905260d8805462ffffff191662ffff001985161761010083021764ffff000000191663010000008702179055855192835290820152928301919091527faf8d657c268b3f943977d5288bfb2306420bcb17b7ef17397cffa5d2f4891643910160405180910390a1505050565b612b75612da7565b6040518060a001604052808681526020018561ffff16815260200184151581526020018381526020018281525060d960008201518160000160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160086101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160000160146101000a81548162ffffff021916908362ffffff16021790555060c08201518160000160176101000a81548162ffffff021916908362ffffff16021790555060e082015181600001601a6101000a81548162ffffff021916908362ffffff16021790555061010082015181600001601d6101000a81548162ffffff021916908362ffffff160217905550505060208201518160010160006101000a81548161ffff021916908361ffff16021790555060408201518160010160026101000a81548160ff02191690831515021790555060608201518160020155608082015181600301559050507f1851d8853c0ab5ed26d95d456344506f759953621e7c115677f2244696b8ba978585858585604051612d9895949392919061568f565b60405180910390a15050505050565b6097546001600160a01b03163314610d675760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b35565b60d054600160301b900460ff1615612e2c5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038216600081815260d66020908152604091829020600381015481546001600160a01b03191690915582516001600160a01b038616815291820181905292917fe8ed5b475a5b5987aa9165e8731bb78043f39eee32ec5a1169a89e27fcd49815910160405180910390a26040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561107a573d6000803e3d6000fd5b6109de612da7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612f0e57610a8783614206565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612f68575060408051601f3d908101601f19168201909252612f6591810190615114565b60015b612fcb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610b35565b600080516020615eb4833981519152811461303a5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610b35565b50610a878383836142a2565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008060c960009054906101000a90046001600160a01b03166001600160a01b031663b330a0fd6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156130ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131169190810190615751565b9050805160000361313a57604051636905ab6760e01b815260040160405180910390fd5b60c954604080516306545a9360e01b815290516000926001600160a01b0316916306545a939160048083019260209291908290030181865afa158015613184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a89190615114565b60cd5490915060009082906131c49063ffffffff16600161516e565b63ffffffff166131d491906157e1565b90505b6131e183826142c7565b61320257816131f182600161518b565b6131fb91906157e1565b90506131d7565b9392505050565b604080514660208201529081018590526001600160401b03841660608201526001600160a01b038316608082015260a0810182905260009060c0016040516020818303038152906040528051906020012060001c90505b949350505050565b60008160405160200161327d91815260200190565b604051602081830303815290604052805190602001209050919050565b60da54600090819062010000900460ff16156132c4575060068601546001600160401b0316613316565b60db5442108015906132d8575060dc544211155b156133165760db54600788015410156132f357506001613316565b600687015461331390600160c01b90046001600160401b031660016150c4565b90505b60006133b2856133276003896157f5565b6133339061c350615812565b61333f89612328615812565b60d0546133599190600160581b900463ffffffff1661516e565b613363919061516e565b60068b0154600160401b90046001600160401b03166133a85760da5460649061ffff1661338f87612397565b6133999190615812565b6133a3919061583a565b6133ab565b60005b878a611693565b905080886004015489600301546133c991906150eb565b10156133e85760405163444a5eaf60e11b815260040160405180910390fd5b808860040160008282546133fc919061518b565b90915550506000878152600589016020526040902081905591505095945050505050565b600054610100900460ff166134475760405162461bcd60e51b8152600401610b359061585d565b610d6761431c565b60405162f577a560e81b8152600481018390526060907334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca89063f577a50090602401602060405180830381865af41580156134a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c591906158b3565b6134e257604051638529df1f60e01b815260040160405180910390fd5b815160000361350457604051638bdcc37560e01b815260040160405180910390fd5b60c9546040516333ad819560e21b8152600481018890526000916001600160a01b03169063ceb6065490602401600060405180830381865afa15801561354e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135769190810190615b60565b90506135868160a001513361434c565b6135a35760405163d9ce719d60e01b815260040160405180910390fd5b60408051602081018890528082018790528151808203830181526060820192839052633033cc5160e01b9092526000907334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca890633033cc51906135fd908590606401615c65565b6040805180830381865af4158015613619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061363d9190615c78565b90507334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca863ebbdac917334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca86313bc64ee896040518263ffffffff1660e01b815260040161369291815260200190565b6040805180830381865af41580156136ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d29190615c78565b856101000151846040518463ffffffff1660e01b81526004016136f793929190615d1e565b602060405180830381865af4158015613714573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061373891906158b3565b61375557604051638baa579f60e01b815260040160405180910390fd5b600085516001600160401b03811115613770576137706147dd565b6040519080825280602002602001820160405280156137a957816020015b61379661476f565b81526020019060019003908161378e5790505b509050600086516001600160401b038111156137c7576137c76147dd565b60405190808252806020026020018201604052801561380057816020015b6137ed61478d565b8152602001906001900390816137e55790505b50905086516001600160401b0381111561381c5761381c6147dd565b604051908082528060200260200182016040528015613845578160200160208202803683370190505b50955060005b8751811015613a92577334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca863f577a50089838151811061388057613880614fe7565b6020026020010151602001516040518263ffffffff1660e01b81526004016138aa91815260200190565b602060405180830381865af41580156138c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138eb91906158b3565b61390857604051636b849b7d60e11b815260040160405180910390fd5b7334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca86313bc64ee89838151811061393457613934614fe7565b6020026020010151602001516040518263ffffffff1660e01b815260040161395e91815260200190565b6040805180830381865af415801561397a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061399e9190615c78565b8382815181106139b0576139b0614fe7565b602002602001018190525085608001518882815181106139d2576139d2614fe7565b602002602001015160000151815181106139ee576139ee614fe7565b602002602001015160200151828281518110613a0c57613a0c614fe7565b60200260200101819052508560800151888281518110613a2e57613a2e614fe7565b60200260200101516000015181518110613a4a57613a4a614fe7565b602002602001015160000151878281518110613a6857613a68614fe7565b6001600160a01b039092166020928302919091019091015280613a8a81615013565b91505061384b565b50604051630d6870d760e21b81527334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca8906335a1c35c90613ace90859085908890600401615d47565b602060405180830381865af4158015613aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0f91906158b3565b613b2c57604051639c2d1c6d60e01b815260040160405180910390fd5b505050505095945050505050565b60008060608184604001516002811115613b5657613b56615295565b03613ba05750604080516024810187905260448082018790528251808303909101815260649091019091526020810180516001600160e01b03166394985ddd60e01b179052613d8a565b600184604001516002811115613bb857613bb8615295565b03613ceb5760008460600151806020019051810190613bd79190615ddd565b905060008163ffffffff166001600160401b03811115613bf957613bf96147dd565b604051908082528060200260200182016040528015613c22578160200160208202803683370190505b50905060005b8263ffffffff16811015613c925760408051602081018a90529081018290526060016040516020818303038152906040528051906020012060001c828281518110613c7557613c75614fe7565b602090810291909101015280613c8a81615013565b915050613c28565b506040516375bf929b60e01b90613caf908a908490602401615dfa565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529250613d8a915050565b600284604001516002811115613d0357613d03615295565b03613d8a5760008460600151806020019051810190613d229190615ddd565b90506000613d368263ffffffff16886143a7565b9050639e5836f660e01b8882604051602401613d53929190615dfa565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152925050505b60d0805466ff0000000000001916600160301b17905560e08401516080850151613dbb9163ffffffff169083614502565b60d0805466ff000000000000191690559695505050505050565b6006840180546000918291600191908390613dfa9084906001600160401b03166150c4565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550600060d960010160029054906101000a900460ff1615613e4c575060068601546001600160401b0316613f03565b60db544210801590613e60575060dc544211155b15613f035760db5460078801541015613ea05760068701805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b179055613eec565b60018760060160188282829054906101000a90046001600160401b0316613ec791906150c4565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b506006860154600160c01b90046001600160401b03165b4260078801556006870154600090600160401b90046001600160401b031615613f765760018860060160088282829054906101000a90046001600160401b0316613f4d9190615e3b565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550613fb5565b60da5460649061ffff16613f8984612397565b613f9e9063ffffffff1664e8d4a5100061512d565b613fa8919061512d565b613fb2919061515a565b90505b6000613fe886613fc78961232861512d565b60d054613fe19190600160381b900463ffffffff1661518b565b843a61454e565b9050808960030154101561400f5760405163964d765f60e01b815260040160405180910390fd5b600088815260058a01602052604081205460048b018054919290916140359084906150eb565b9091555050600088815260058a016020526040812081905560038a0180548392906140619084906150eb565b925050819055508160ca600082825461407a919061518b565b909155509099919850909650505050505050565b60d35460cb80546000906140a390849061518b565b9091555050825160d2546140b7919061512d565b60cc60008282546140c8919061518b565b909155505060408051600180825281830190925260009160208083019080368337019050509050338160008151811061410357614103614fe7565b6001600160a01b03928316602091820292909201015260c9541663914eb34d8261412d85876150eb565b60d3546040516001600160e01b031960e086901b16815261415393929190600401615e5b565b600060405180830381600087803b15801561416d57600080fd5b505af1158015614181573d6000803e3d6000fd5b505060c95486516001600160a01b03909116925063914eb34d915086906141a8908661515a565b60d2546040516001600160e01b031960e086901b1681526141ce93929190600401615e5b565b600060405180830381600087803b1580156141e857600080fd5b505af11580156141fc573d6000803e3d6000fd5b5050505050505050565b6001600160a01b0381163b6142735760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b35565b600080516020615eb483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6142ab836145fd565b6000825111806142b85750805b15610a875761107a838361463d565b6000805b835181101561431057828482815181106142e7576142e7614fe7565b6020026020010151036142fe576001915050614316565b8061430881615013565b9150506142cb565b50600090505b92915050565b600054610100900460ff166143435760405162461bcd60e51b8152600401610b359061585d565b610d6733613046565b6000805b835181101561431057826001600160a01b031684828151811061437557614375614fe7565b60200260200101516001600160a01b031603614395576001915050614316565b8061439f81615013565b915050614350565b60606000836001600160401b038111156143c3576143c36147dd565b6040519080825280602002602001820160405280156143ec578160200160208202803683370190505b50905060005b8481101561442a578082828151811061440d5761440d614fe7565b60209081029190910101528061442281615013565b9150506143f2565b5080516000805b600061443c84615e80565b93508311156144f75761444f83876157e1565b91508560405160200161446491815260200190565b6040516020818303038152906040528051906020012060001c955083838151811061449157614491614fe7565b602002602001015190508382815181106144ad576144ad614fe7565b60200260200101518484815181106144c7576144c7614fe7565b602002602001018181525050808483815181106144e6576144e6614fe7565b602002602001018181525050614431565b509195945050505050565b60005a61138881101561451457600080fd5b61138881039050846040820482031161452c57600080fd5b50823b61453857600080fd5b60008083516020850160008789f1949350505050565b600080738ffe9b19591b031c7b76a27d1b356ed0a8441b8063c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865af415801561459a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145be9190615114565b5a6145c9888861518b565b6145d391906150eb565b6145dd908561512d565b6145e7919061518b565b90506145f3848261518b565b9695505050505050565b61460681614206565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6146a55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b35565b600080846001600160a01b0316846040516146c09190615e97565b600060405180830381855af49150503d80600081146146fb576040519150601f19603f3d011682016040523d82523d6000602084013e614700565b606091505b50915091506147288282604051806060016040528060278152602001615ed460279139614731565b95945050505050565b60608315614740575081613202565b61320283838151156147555781518083602001fd5b8060405162461bcd60e51b8152600401610b359190615c65565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b80356001600160401b0381168114611cf857600080fd5b6000602082840312156147d457600080fd5b613202826147ab565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715614816576148166147dd565b60405290565b60405160e081016001600160401b0381118282101715614816576148166147dd565b604080519081016001600160401b0381118282101715614816576148166147dd565b60405161014081016001600160401b0381118282101715614816576148166147dd565b604051606081016001600160401b0381118282101715614816576148166147dd565b604051601f8201601f191681016001600160401b03811182821017156148cd576148cd6147dd565b604052919050565b60006001600160401b038211156148ee576148ee6147dd565b5060051b60200190565b600082601f83011261490957600080fd5b8135602061491e614919836148d5565b6148a5565b82815260059290921b8401810191818101908684111561493d57600080fd5b8286015b8481101561495f57614952816147ab565b8352918301918301614941565b509695505050505050565b6000806040838503121561497d57600080fd5b82356001600160401b038082111561499457600080fd5b6149a0868387016148f8565b935060208501359150808211156149b657600080fd5b506149c3858286016148f8565b9150509250929050565b6001600160a01b03811681146109de57600080fd5b8035611cf8816149cd565b60008060408385031215614a0057600080fd5b8235614a0b816149cd565b946020939093013593505050565b600060208284031215614a2b57600080fd5b5035919050565b600060208284031215614a4457600080fd5b8135613202816149cd565b600082601f830112614a6057600080fd5b81356001600160401b03811115614a7957614a796147dd565b614a8c601f8201601f19166020016148a5565b818152846020838601011115614aa157600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614ad157600080fd5b8235614adc816149cd565b915060208301356001600160401b03811115614af757600080fd5b6149c385828601614a4f565b803561ffff81168114611cf857600080fd5b63ffffffff811681146109de57600080fd5b8035611cf881614b15565b600080600080600080600060e0888a031215614b4d57600080fd5b614b5688614b03565b96506020880135614b6681614b15565b95506040880135614b7681614b15565b94506060880135614b8681614b15565b9699959850939660808101359560a0820135955060c0909101359350915050565b60008060408385031215614bba57600080fd5b614bc3836147ab565b91506020830135614bd3816149cd565b809150509250929050565b60008060408385031215614bf157600080fd5b614bfa836147ab565b9150614c08602084016147ab565b90509250929050565b600080600080600060a08688031215614c2957600080fd5b8535614c3481614b15565b94506020860135614c4481614b15565b93506040860135614c5481614b15565b9250606086013591506080860135614c6b81614b15565b809150509295509295909350565b600060208284031215614c8b57600080fd5b81356001600160401b03811115614ca157600080fd5b820160e0818503121561320257600080fd5b600081518084526020808501945080840160005b83811015614cec5781516001600160a01b031687529582019590820190600101614cc7565b509495945050505050565b60006101206001600160a01b038c168352806020840152614d1a8184018c614cb3565b604084019a909a52505060608101969096526001600160401b03948516608087015292841660a086015290831660c085015290911660e08301526101009091015292915050565b60006101408284031215614d7457600080fd5b50919050565b60008060008060008060a08789031215614d9357600080fd5b8635614d9e81614b15565b9550602087013594506040870135935060608701356001600160401b0380821115614dc857600080fd5b614dd48a838b01614d61565b94506080890135915080821115614dea57600080fd5b818901915089601f830112614dfe57600080fd5b813581811115614e0d57600080fd5b8a60208260061b8501011115614e2257600080fd5b6020830194508093505050509295509295509295565b60008060408385031215614e4b57600080fd5b8235915060208301356001600160401b03811115614e6857600080fd5b6149c385828601614d61565b80151581146109de57600080fd5b8035611cf881614e74565b600080600060608486031215614ea257600080fd5b8335614ead81614e74565b9250614ebb60208501614b03565b9150614ec960408501614b03565b90509250925092565b803562ffffff81168114611cf857600080fd5b60008060008060008587036101a0811215614eff57600080fd5b61012080821215614f0f57600080fd5b614f176147f3565b9150614f2288614b27565b8252614f3060208901614b27565b6020830152614f4160408901614b27565b6040830152614f5260608901614b27565b6060830152614f6360808901614b27565b6080830152614f7460a08901614ed2565b60a0830152614f8560c08901614ed2565b60c0830152614f9660e08901614ed2565b60e0830152610100614fa9818a01614ed2565b8184015250819650614fbc818901614b03565b95505050614fcd6101408701614e82565b949793965093946101608101359450610180013592915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161502557615025614ffd565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6001600160401b038181168382160190808211156150e4576150e4614ffd565b5092915050565b8181038181111561431657614316614ffd565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561512657600080fd5b5051919050565b808202811582820484141761431657614316614ffd565b634e487b7160e01b600052601260045260246000fd5b60008261516957615169615144565b500490565b63ffffffff8181168382160190808211156150e4576150e4614ffd565b8082018082111561431657614316614ffd565b60006001600160401b038083168181036151ba576151ba614ffd565b6001019392505050565b803560038110611cf857600080fd5b600060e082360312156151e557600080fd5b6151ed61481c565b6151f6836151c4565b815260208301356001600160401b0381111561521157600080fd5b61521d36828601614a4f565b60208301525061522f604084016147ab565b60408201526060830135606082015261524a60808401614b03565b608082015261525b60a08401614b27565b60a082015260c092830135928101929092525090565b6000806040838503121561528457600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fd5b600381106152c957634e487b7160e01b600052602160045260246000fd5b9052565b60005b838110156152e85781810151838201526020016152d0565b50506000910152565b600081518084526153098160208601602086016152cd565b601f01601f19169290920160200192915050565b60006101608d83526001600160401b038d16602084015263ffffffff808d16604085015261534e606085018d6152ab565b8160808501526153608285018c6152f1565b6001600160a01b039a909a1660a085015260c0840198909852505061ffff9490941660e085015291909316610100830152610120820192909252610140015295945050505050565b60006101006153b7838c6152ab565b8060208401526153c98184018b6152f1565b6001600160a01b039990991660408401525050606081019590955261ffff93909316608085015263ffffffff9190911660a084015260c083015260e09091015292915050565b60006020828403121561542157600080fd5b813561320281614b15565b60006020828403121561543e57600080fd5b613202826151c4565b6000808335601e1984360301811261545e57600080fd5b8301803591506001600160401b0382111561547857600080fd5b60200191503681900382131561548d57600080fd5b9250929050565b6000602082840312156154a657600080fd5b61320282614b03565b60006101608e83526001600160401b038e16602084015263ffffffff8d1660408401526154df606084018d6152ab565b806080840152898184015250610180898b8285013760008a84018201526001600160a01b03891660a0840152601f19601f8b011683010190508660c083015261552e60e083018761ffff169052565b63ffffffff851661010083015261012082019390935261014001529a9950505050505050505050565b60006040828403121561556957600080fd5b61557161483e565b82358152602083013560208201528091505092915050565b6000610140823603121561559c57600080fd5b6155a4614860565b6155ad836147ab565b81526155bb60208401614b27565b60208201526155cc604084016151c4565b604082015260608301356001600160401b038111156155ea57600080fd5b6155f636828601614a4f565b606083015250615608608084016149e2565b608082015260a083013560a082015261562360c08401614b03565b60c082015261563460e08401614b27565b60e0820152610100838101359082015261012092830135928101929092525090565b60a08152600061566960a0830188614cb3565b905085602083015284604083015283606083015282151560808301529695505050505050565b855163ffffffff9081168252602080880151821690830152604080880151821690830152606080880151821690830152608080880151918216908301526101a08201905060a08701516156e960a084018262ffffff169052565b5060c087015161570060c084018262ffffff169052565b5060e087015161571760e084018262ffffff169052565b506101009687015162ffffff169682019690965261ffff949094166101208501529115156101408401526101608301526101809091015290565b6000602080838503121561576457600080fd5b82516001600160401b0381111561577a57600080fd5b8301601f8101851361578b57600080fd5b8051615799614919826148d5565b81815260059190911b820183019083810190878311156157b857600080fd5b928401925b828410156157d6578351825292840192908401906157bd565b979650505050505050565b6000826157f0576157f0615144565b500690565b63ffffffff8281168282160390808211156150e4576150e4614ffd565b63ffffffff81811683821602808216919082811461583257615832614ffd565b505092915050565b600063ffffffff8084168061585157615851615144565b92169190910492915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8051611cf881614e74565b6000602082840312156158c557600080fd5b815161320281614e74565b600082601f8301126158e157600080fd5b604051608081018181106001600160401b0382111715615903576159036147dd565b60405280608084018581111561591857600080fd5b845b818110156144f757805183526020928301920161591a565b600082601f83011261594357600080fd5b81516020615953614919836148d5565b82815260a0928302850182019282820191908785111561597257600080fd5b8387015b858110156159c05781818a03121561598e5760008081fd5b61599661483e565b81516159a1816149cd565b81526159af8a8388016158d0565b818701528452928401928101615976565b5090979650505050505050565b600082601f8301126159de57600080fd5b815160206159ee614919836148d5565b82815260059290921b84018101918181019086841115615a0d57600080fd5b8286015b8481101561495f578051615a24816149cd565b8352918301918301615a11565b600082601f830112615a4257600080fd5b81516020615a52614919836148d5565b82815260059290921b84018101918181019086841115615a7157600080fd5b8286015b8481101561495f5780516001600160401b0380821115615a9457600080fd5b908801906040601f19838c038101821315615aae57600080fd5b615ab661483e565b8885015184811115615ac757600080fd5b615ad58e8b838901016159cd565b8252508285015184811115615ae957600080fd5b949094019360c0858e0383011215615b015760008081fd5b615b09614883565b9150888501518252615b1d8d8487016158d0565b8983015260c085015184811115615b345760008081fd5b615b428e8b838901016159cd565b93830193909352808901919091528652505050918301918301615a75565b600060208284031215615b7257600080fd5b81516001600160401b0380821115615b8957600080fd5b908301906101808286031215615b9e57600080fd5b615ba66147f3565b82518152602083015160208201526040830151604082015260608301516060820152608083015182811115615bda57600080fd5b615be687828601615932565b60808301525060a083015182811115615bfe57600080fd5b615c0a878286016159cd565b60a08301525060c083015182811115615c2257600080fd5b615c2e87828601615a31565b60c083015250615c4060e084016158a8565b60e08201526101009150615c56868385016158d0565b91810191909152949350505050565b60208152600061320260208301846152f1565b600060408284031215615c8a57600080fd5b82601f830112615c9957600080fd5b615ca161483e565b806040840185811115615cb357600080fd5b845b81811015615ccd578051845260209384019301615cb5565b509095945050505050565b8060005b600281101561107a578151845260209384019390910190600101615cdc565b8060005b600481101561107a578151845260209384019390910190600101615cff565b6101008101615d2d8286615cd8565b615d3a6040830185615cfb565b61326060c0830184615cd8565b608080825284518282018190526000919060209060a0850190828901855b82811015615d8b57615d78848351615cd8565b6040939093019290840190600101615d65565b5050508481038286015286518082528783019183019060005b81811015615dc757615db7838551615cfb565b9284019291850191600101615da4565b5050809450505050506132606040830184615cd8565b600060208284031215615def57600080fd5b815161320281614b15565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156159c057845183529383019391830191600101615e1f565b6001600160401b038281168282160390808211156150e4576150e4614ffd565b606081526000615e6e6060830186614cb3565b60208301949094525060400152919050565b600081615e8f57615e8f614ffd565b506000190190565b60008251615ea98184602087016152cd565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c8bc09fbba0404d1748ce032f33b2c531725d05734c46b60697551ef575283be64736f6c63430008120033
Deployed Bytecode
0x6080604052600436106102565760003560e01c806391a6fe7711610149578063c725a833116100c6578063dcdb7b881161008a578063f2fde38b11610064578063f2fde38b1461090a578063f362ca611461092a578063f4cc97fc1461094a57600080fd5b8063dcdb7b8814610721578063dfaba79414610889578063ef6f42731461089c57600080fd5b8063c725a83314610670578063caba5284146106a1578063d2f9f9a7146106c1578063d7ae1d30146106e1578063d89f241f1461070157600080fd5b8063a39402d71161010d578063a39402d7146105d1578063a47c7696146105f1578063a4c343f214610626578063aa81d59a1461063b578063c4d66de81461065057600080fd5b806391a6fe7714610541578063931d92041461055c5780639f87fad71461057c578063a141bbd81461059c578063a21a23e4146105bc57600080fd5b806352d1902d116101d75780637341c10c1161019b5780637341c10c1461048057806376a911bc146104a05780638166d459146104e2578063877d38bb1461050d5780638da5cb5b1461052357600080fd5b806352d1902d1461040c578063636021741461042157806364d51a2a14610436578063715018a61461044b57806371b7ca051461046057600080fd5b806315c48b841161021e57806315c48b841461032f5780631e58a872146103575780633018205f146103a75780633659cfe6146103d95780634f1ef286146103f957600080fd5b806302bcc5b61461025b578063056e5ede1461027d57806306bfa6371461029d5780630ad98f6a146102d45780631565034c146102f4575b600080fd5b34801561026757600080fd5b5061027b6102763660046147c2565b61096a565b005b34801561028957600080fd5b5061027b61029836600461496a565b6109e1565b3480156102a957600080fd5b5060d7546001600160401b03165b6040516001600160401b0390911681526020015b60405180910390f35b3480156102e057600080fd5b5061027b6102ef3660046149ed565b610a8c565b34801561030057600080fd5b5061032161030f366004614a19565b600090815260d4602052604090205490565b6040519081526020016102cb565b34801561033b57600080fd5b5061034460c881565b60405161ffff90911681526020016102cb565b34801561036357600080fd5b5061038560d85460ff81169161ffff6101008304811692630100000090041690565b60408051931515845261ffff92831660208501529116908201526060016102cb565b3480156103b357600080fd5b5060c9546001600160a01b03165b6040516001600160a01b0390911681526020016102cb565b3480156103e557600080fd5b5061027b6103f4366004614a32565b610aed565b61027b610407366004614abe565b610bd2565b34801561041857600080fd5b50610321610ca2565b34801561042d57600080fd5b5060cf54610321565b34801561044257600080fd5b50610344606481565b34801561045757600080fd5b5061027b610d55565b34801561046c57600080fd5b5061027b61047b366004614b32565b610d69565b34801561048c57600080fd5b5061027b61049b366004614ba7565b610ebd565b3480156104ac57600080fd5b506102b76104bb366004614a32565b6001600160a01b0316600090815260d560205260409020600101546001600160401b031690565b3480156104ee57600080fd5b506104f861232881565b60405163ffffffff90911681526020016102cb565b34801561051957600080fd5b506104f861c35081565b34801561052f57600080fd5b506097546001600160a01b03166103c1565b34801561054d57600080fd5b5060cd5463ffffffff16610321565b34801561056857600080fd5b5061027b610577366004614bde565b611080565b34801561058857600080fd5b5061027b610597366004614ba7565b61135d565b3480156105a857600080fd5b506103216105b7366004614c11565b611693565b3480156105c857600080fd5b506102b76117e6565b3480156105dd57600080fd5b506103216105ec366004614c79565b6118df565b3480156105fd57600080fd5b5061061161060c3660046147c2565b611cfd565b6040516102cb99989796959493929190614cf7565b34801561063257600080fd5b5060ce54610321565b34801561064757600080fd5b506104f8600381565b34801561065c57600080fd5b5061027b61066b366004614a32565b611e1d565b34801561067c57600080fd5b5060ca5460cb5460cc54604080519384526020840192909252908201526060016102cb565b3480156106ad57600080fd5b5061027b6106bc366004614d7a565b611f49565b3480156106cd57600080fd5b506104f86106dc3660046147c2565b612397565b3480156106ed57600080fd5b5061027b6106fc366004614ba7565b612514565b34801561070d57600080fd5b5061027b61071c366004614e38565b612620565b34801561072d57600080fd5b50604080516101208101825260d95463ffffffff8082168084526401000000008304821660208501819052600160401b84048316958501869052600160601b8404831660608601819052600160801b85049093166080860181905262ffffff600160a01b8604811660a08801819052600160b81b8704821660c08901819052600160d01b8804831660e08a01819052600160e81b90980490921661010090980188905260da5460db5460dc54969a95999598949692959394939261ffff83169260ff620100009091041691906040516102cb9d9c9b9a9998979695949392919063ffffffff9d8e1681529b8d1660208d0152998c1660408c0152978b1660608b015295909916608089015262ffffff93841660a089015291831660c0880152821660e08701521661010085015261ffff949094166101208401529215156101408301526101608201929092526101808101919091526101a00190565b61027b6108973660046147c2565b612971565b3480156108a857600080fd5b5060d05460d15460d25460d3546040805161ffff8616815263ffffffff62010000870481166020830152600160381b8704811692820192909252600160581b909504166060850152608084019290925260a083015260c082015260e0016102cb565b34801561091657600080fd5b5061027b610925366004614a32565b612a5d565b34801561093657600080fd5b5061027b610945366004614e8d565b612ad3565b34801561095657600080fd5b5061027b610965366004614ee5565b612b6d565b610972612da7565b6001600160401b038116600090815260d660205260409020546001600160a01b03166109b157604051630fb532db60e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260409020546109de9082906001600160a01b0316612e01565b50565b6109e9612da7565b60005b8251811015610a8757818181518110610a0757610a07614fe7565b602002602001015160d66000858481518110610a2557610a25614fe7565b60200260200101516001600160401b03166001600160401b0316815260200190815260200160002060060160086101000a8154816001600160401b0302191690836001600160401b031602179055508080610a7f90615013565b9150506109ec565b505050565b60c9546001600160a01b03163314610ab757604051630f5caa3360e41b815260040160405180910390fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610a87573d6000803e3d6000fd5b6001600160a01b037f00000000000000000000000025f9dcf802bdc0cb6955f684cbb94e10ee7e9f4f163003610b3e5760405162461bcd60e51b8152600401610b359061502c565b60405180910390fd5b7f00000000000000000000000025f9dcf802bdc0cb6955f684cbb94e10ee7e9f4f6001600160a01b0316610b87600080516020615eb4833981519152546001600160a01b031690565b6001600160a01b031614610bad5760405162461bcd60e51b8152600401610b3590615078565b610bb681612ed3565b604080516000808252602082019092526109de91839190612edb565b6001600160a01b037f00000000000000000000000025f9dcf802bdc0cb6955f684cbb94e10ee7e9f4f163003610c1a5760405162461bcd60e51b8152600401610b359061502c565b7f00000000000000000000000025f9dcf802bdc0cb6955f684cbb94e10ee7e9f4f6001600160a01b0316610c63600080516020615eb4833981519152546001600160a01b031690565b6001600160a01b031614610c895760405162461bcd60e51b8152600401610b3590615078565b610c9282612ed3565b610c9e82826001612edb565b5050565b6000306001600160a01b037f00000000000000000000000025f9dcf802bdc0cb6955f684cbb94e10ee7e9f4f1614610d425760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610b35565b50600080516020615eb483398151915290565b610d5d612da7565b610d676000613046565b565b610d71612da7565b60c861ffff88161115610dab5760405163539c34bb60e11b815261ffff881660048201819052602482015260c86044820152606401610b35565b604080516101008101825261ffff891680825263ffffffff89811660208085018290526000858701528a83166060808701829052938b16608080880182905260a08089018d905260c0808a018d905260e0998a018c905260d0805465ffffffffffff19168a17620100008902176effffffffffffffffff0000000000001916600160381b87026effffffff0000000000000000000000191617600160581b860217905560d18e905560d28d905560d38c90558a519889529488019590955297860191909152928401929092529382018790529281018590529182018390527fefeb3292465cf72a302efdd83695ad560a2828353a1e018844e9abd19a642037910160405180910390a150505050505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b031680610eff57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b03821614610f3357604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff1615610f5e5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038416600090815260d6602052604090206002015460631901610f9b576040516305a48e0f60e01b815260040160405180910390fd5b6001600160a01b038316600090815260d5602090815260408083206001600160401b038089168552925282205416900361107a576001600160a01b038316600081815260d5602090815260408083206001600160401b0389168085528184528285208054600167ffffffffffffffff1991821681179092559281018054909316821790925560d68452828520600201805492830181558552938390200180546001600160a01b031916851790555192835290917f43dc749a04ac8fb825cbd514f7c0e13f13bc6f2ee66043b76629d51776cff8e0910160405180910390a25b50505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b0316806110c257604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146110f657604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156111215760405163769dd35360e11b815260040160405180910390fd5b60d85460ff1661114457604051636dac270160e01b815260040160405180910390fd5b6001600160401b03808416600090815260d660205260408082205492871682529020546001600160a01b039182169116036111925760405163027f035560e51b815260040160405180910390fd5b6001600160401b03808516600090815260d66020526040902060060154600160801b900416156111d55760405163cae26ee160e01b815260040160405180910390fd5b6001600160401b03808516600090815260d6602052604090206006015416158061121a57506001600160401b03808416600090815260d6602052604090206006015416155b156112385760405163a760a23760e01b815260040160405180910390fd5b60d8546001600160401b03848116600090815260d660205260409020600601805461010090930461ffff1692909160089161127c918591600160401b9004166150c4565b82546101009290920a6001600160401b0381810219909316918316021790915560d854868216600090815260d6602052604090206006018054630100000090920461ffff169350916008916112da918591600160401b9004166150c4565b82546101009290920a6001600160401b03818102199093169183160217909155858116600081815260d66020526040808220600601805467ffffffffffffffff60801b1916600160801b958a169586021790555192935090917fb661d46b53034f62a6c7d50df2a5e055fab98889aaf62f8c618e457edd96c6889190a350505050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b03168061139f57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146113d357604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156113fe5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038416600090815260d660205260409020600401541561143857604051631685ecdd60e31b815260040160405180910390fd5b6001600160401b038416600090815260d660209081526040808320600201805482518185028101850190935280835291929091908301828280156114a557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611487575b5050505050905080516000036114e857604051637800cff360e11b81526001600160401b03861660048201526001600160a01b0385166024820152604401610b35565b60005b815181101561165f57846001600160a01b031682828151811061151057611510614fe7565b60200260200101516001600160a01b03160361164d57816001835161153591906150eb565b8151811061154557611545614fe7565b602002602001015160d66000886001600160401b03166001600160401b03168152602001908152602001600020600201828154811061158657611586614fe7565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394909416939093179092556001600160401b038816815260d6909152604090206002018054806115da576115da6150fe565b6000828152602090819020600019908301810180546001600160a01b03191690559091019091556040516001600160a01b03871681526001600160401b038816917f182bff9831466789164ca77075fffd84916d35a8180ba73c27e45634549b445b910160405180910390a2505061107a565b8061165781615013565b9150506114eb565b50604051637800cff360e11b81526001600160401b03861660048201526001600160a01b0385166024820152604401610b35565b60405163745e0dcf60e01b815263ffffffff821660048201526000908190600290738ffe9b19591b031c7b76a27d1b356ed0a8441b8090638e3976f690829063745e0dcf90602401602060405180830381865af41580156116f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171c9190615114565b6040518263ffffffff1660e01b815260040161173a91815260200190565b602060405180830381865af4158015611757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177b9190615114565b61178690600361512d565b611790919061515a565b905060008161179f898961516e565b6117af9063ffffffff168761512d565b6117b9919061518b565b90506117d063ffffffff871664e8d4a5100061512d565b6117da908261518b565b98975050505050505050565b60d054600090600160301b900460ff16156118145760405163769dd35360e11b815260040160405180910390fd5b60d780546001600160401b031690600061182d8361519e565b82546001600160401b039182166101009390930a92830292820219169190911790915560d780548216600090815260d6602052604080822080546001600160a01b0319163390811790915583548516835281832060060180546fffffffffffffffff00000000000000001916600160401b17905592549051929450909216917f464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf91a35060d7546001600160401b031690565b60d054600090600160301b900460ff161561190d5760405163769dd35360e11b815260040160405180910390fd5b6000611918836151d3565b905032330361193a57604051638a3150e760e01b815260040160405180910390fd5b6040808201516001600160401b0316600090815260d66020522080546001600160a01b031661197c57604051630fb532db60e11b815260040160405180910390fd5b33600090815260d560209081526040808320858201516001600160401b03908116855292528220541690036119db576040808301519051637800cff360e11b81526001600160401b039091166004820152336024820152604401610b35565b60d054608083015161ffff91821691161080611a03575060c861ffff16826080015161ffff16115b15611a3e57608082015160d05460405163539c34bb60e11b815261ffff92831660048201529116602482015260c86044820152606401610b35565b60d05460a083015163ffffffff62010000909204821691161115611a955760a082015160d054604051637aebf00f60e11b815263ffffffff9283166004820152620100009091049091166024820152604401610b35565b611a9d613098565b60cd805463ffffffff191663ffffffff9290921691909117905560608201516040808401805133600081815260d5602090815285822094516001600160401b039081168352949052938420549394611af794909316613209565b6040848101805133600090815260d560209081528482206001808201805467ffffffffffffffff19166001600160401b03968716179055945184168352905292832080549495509193919291611b4f918591166150c4565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506000611b7e82613268565b60c95460cd5460405163f49e0ba960e01b815263ffffffff90911660048201529192506000916001600160a01b039091169063f49e0ba9906024016040805180830381865afa158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615271565b9150506000611c138584848960a001518a60c0015161329a565b60408088015160cd5489516020808c015160808d015160a08e015160c08f01519751989950611c59988c9863ffffffff90971696939433948f949392909143910161531d565b60408051601f198184030181528282528051602091820120600087815260d483528390205560cd54918901518951918a015160808b015160a08c015160c08d015163ffffffff909616966001600160401b03909416958a957fd26299589dd9197a8dc30a0fa17b0fe7dd432bc3441aa5f5631ea1e14c1af74495611ce7959194919333938f93928d906153a8565b60405180910390a450909450505050505b919050565b6001600160401b038116600090815260d660205260408120805460609183918291829182918291829182916001600160a01b0316611d4e57604051630fb532db60e11b815260040160405180910390fd5b80546003820154600483015460068401546007850154600286018054604080516020808402820181019092528281526001600160a01b0390981697929695946001600160401b0380821695600160401b8304821695600160801b8404831695600160c01b9094049092169390928a91830182828015611df657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611dd8575b50505050509750995099509950995099509950995099509950509193959799909294969850565b600054610100900460ff1615808015611e3d5750600054600160ff909116105b80611e575750303b158015611e57575060005460ff166001145b611eba5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b35565b6000805460ff191660011790558015611edd576000805461ff0019166101001790555b60c980546001600160a01b0319166001600160a01b038416179055611f00613420565b8015610c9e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60d054600160301b900460ff1615611f745760405163769dd35360e11b815260040160405180910390fd5b60005a600087815260d46020526040812054919250819003611fa957604051631b44092560e11b815260040160405180910390fd5b86611fb760208701876147c2565b611fc7604088016020890161540f565b611fd76060890160408a0161542c565b611fe460608a018a615447565b611ff460a08c0160808d01614a32565b60a08c013561200960e08e0160c08f01615494565b8d60e001602081019061201c919061540f565b8e61010001358f61012001356040516020016120439c9b9a999897969594939291906154af565b6040516020818303038152906040528051906020012081146120785760405163354a450b60e21b815260040160405180910390fd5b61208860e0860160c08701615494565b61209b9061ffff1661012087013561518b565b4310156120bb5760405163619a4abd60e01b815260040160405180910390fd5b6120cb604086016020870161540f565b63ffffffff168863ffffffff16141580156120f7575060d1546120f39061012087013561518b565b4311155b15612115576040516378373bbd60e11b815260040160405180910390fd5b60c960009054906101000a90046001600160a01b03166001600160a01b03166306545a936040518163ffffffff1660e01b8152600401602060405180830381865afa158015612168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218c9190615114565b8863ffffffff16106121b957604051637f6efcb560e11b815263ffffffff89166004820152602401610b35565b60006122298963ffffffff168760a001358861012001358a8989808060200260200160405190810160405280939291908181526020016000905b8282101561221f5761221060408302860136819003810190615557565b815260200190600101906121f3565b505050505061344f565b600089815260d46020908152604080832083905580518083018c9052815180820384018152908201909152805191012060cf805493945090926001929061227190849061518b565b909155505060ce81905560c9546040516379ef840160e11b8152600481018390526001600160a01b039091169063f3df080290602401600060405180830381600087803b1580156122c157600080fd5b505af11580156122d5573d6000803e3d6000fd5b5050505060006122ef8a838a6122ea90615589565b613b3a565b905060008061232860d68261230760208e018e6147c2565b6001600160401b0316815260208101919091526040016000208d8a8a613dd5565b9150915061233785838361408e565b336001600160a01b03168d63ffffffff168d7f6fc1bcb4bd7d5fdf4017f746304b61ae4472496256e906c6bb44682aa2c9a6d8888887878a604051612380959493929190615656565b60405180910390a450505050505050505050505050565b604080516101208101825260d95463ffffffff8082168352640100000000820481166020840152600160401b8204811693830193909352600160601b810483166060830152600160801b8104909216608082015262ffffff600160a01b8304811660a08301819052600160b81b8404821660c0840152600160d01b8404821660e0840152600160e81b909304166101008201526000916001600160401b03841611612443575192915050565b826001600160401b03168160a0015162ffffff1610801561247657508060c0015162ffffff16836001600160401b031611155b15612485576020015192915050565b826001600160401b03168160c0015162ffffff161080156124b857508060e0015162ffffff16836001600160401b031611155b156124c7576040015192915050565b826001600160401b03168160e0015162ffffff161080156124fb575080610100015162ffffff16836001600160401b031611155b1561250a576060015192915050565b6080015192915050565b6001600160401b038216600090815260d6602052604090205482906001600160a01b03168061255657604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b0382161461258a57604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b60d054600160301b900460ff16156125b55760405163769dd35360e11b815260040160405180910390fd5b6001600160a01b0383166125dc5760405163f6b2911f60e01b815260040160405180910390fd5b6001600160401b038416600090815260d660205260409020600401541561261657604051631685ecdd60e31b815260040160405180910390fd5b61107a8484612e01565b61262d60208201826147c2565b6001600160401b038116600090815260d660205260409020546001600160a01b03168061266d57604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146126a157604051636c51fda960e11b81526001600160a01b0382166004820152602401610b35565b600084815260d4602052604081205490036126cf57604051631b44092560e11b815260040160405180910390fd5b836126dd60208501856147c2565b6126ed604086016020870161540f565b6126fd606087016040880161542c565b61270a6060880188615447565b61271a60a08a0160808b01614a32565b60a08a013561272f60e08c0160c08d01615494565b6127406101008d0160e08e0161540f565b8c61010001358d61012001356040516020016127679c9b9a999897969594939291906154af565b60408051601f198184030181529181528151602092830120600087815260d4909352912054146127aa5760405163354a450b60e21b815260040160405180910390fd5b6000738ffe9b19591b031c7b76a27d1b356ed0a8441b806387ceff096040518163ffffffff1660e01b8152600401602060405180830381865af41580156127f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128199190615114565b612826906201518061515a565b90506128378161012086013561518b565b43101561285757604051636c804b5d60e01b815260040160405180910390fd5b600085815260d460209081526040822082905560d6919061287a908701876147c2565b6001600160401b03168152602080820192909252604090810160009081208882526005018352908120549160d691906128b5908801886147c2565b6001600160401b03166001600160401b0316815260200190815260200160002060040160008282546128e791906150eb565b9091555060d6905060006128fe60208701876147c2565b6001600160401b0316815260208082019290925260409081016000908120888252600501835290812055612934908501856147c2565b6001600160401b0316857fc1cf1d318384ee8dee53eed48bbf121b2b14fa61e9da5fd2f597dfbee4e5c2e660405160405180910390a35050505050565b60d054600160301b900460ff161561299c5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260409020546001600160a01b03166129db57604051630fb532db60e11b815260040160405180910390fd5b6001600160401b038116600090815260d660205260408120600301805491349190612a06838561518b565b90915550506001600160401b0382167fd39ec07f4e209f627a4c427971473820dc129761ba28de8906bd56f57101d4f882612a41348261518b565b6040805192835260208301919091520160405180910390a25050565b612a65612da7565b6001600160a01b038116612aca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b35565b6109de81613046565b612adb612da7565b604080516060808201835285151580835261ffff868116602080860182905291871694860185905260d8805462ffffff191662ffff001985161761010083021764ffff000000191663010000008702179055855192835290820152928301919091527faf8d657c268b3f943977d5288bfb2306420bcb17b7ef17397cffa5d2f4891643910160405180910390a1505050565b612b75612da7565b6040518060a001604052808681526020018561ffff16815260200184151581526020018381526020018281525060d960008201518160000160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160086101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160000160146101000a81548162ffffff021916908362ffffff16021790555060c08201518160000160176101000a81548162ffffff021916908362ffffff16021790555060e082015181600001601a6101000a81548162ffffff021916908362ffffff16021790555061010082015181600001601d6101000a81548162ffffff021916908362ffffff160217905550505060208201518160010160006101000a81548161ffff021916908361ffff16021790555060408201518160010160026101000a81548160ff02191690831515021790555060608201518160020155608082015181600301559050507f1851d8853c0ab5ed26d95d456344506f759953621e7c115677f2244696b8ba978585858585604051612d9895949392919061568f565b60405180910390a15050505050565b6097546001600160a01b03163314610d675760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b35565b60d054600160301b900460ff1615612e2c5760405163769dd35360e11b815260040160405180910390fd5b6001600160401b038216600081815260d66020908152604091829020600381015481546001600160a01b03191690915582516001600160a01b038616815291820181905292917fe8ed5b475a5b5987aa9165e8731bb78043f39eee32ec5a1169a89e27fcd49815910160405180910390a26040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561107a573d6000803e3d6000fd5b6109de612da7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612f0e57610a8783614206565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612f68575060408051601f3d908101601f19168201909252612f6591810190615114565b60015b612fcb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610b35565b600080516020615eb4833981519152811461303a5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610b35565b50610a878383836142a2565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008060c960009054906101000a90046001600160a01b03166001600160a01b031663b330a0fd6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156130ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131169190810190615751565b9050805160000361313a57604051636905ab6760e01b815260040160405180910390fd5b60c954604080516306545a9360e01b815290516000926001600160a01b0316916306545a939160048083019260209291908290030181865afa158015613184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a89190615114565b60cd5490915060009082906131c49063ffffffff16600161516e565b63ffffffff166131d491906157e1565b90505b6131e183826142c7565b61320257816131f182600161518b565b6131fb91906157e1565b90506131d7565b9392505050565b604080514660208201529081018590526001600160401b03841660608201526001600160a01b038316608082015260a0810182905260009060c0016040516020818303038152906040528051906020012060001c90505b949350505050565b60008160405160200161327d91815260200190565b604051602081830303815290604052805190602001209050919050565b60da54600090819062010000900460ff16156132c4575060068601546001600160401b0316613316565b60db5442108015906132d8575060dc544211155b156133165760db54600788015410156132f357506001613316565b600687015461331390600160c01b90046001600160401b031660016150c4565b90505b60006133b2856133276003896157f5565b6133339061c350615812565b61333f89612328615812565b60d0546133599190600160581b900463ffffffff1661516e565b613363919061516e565b60068b0154600160401b90046001600160401b03166133a85760da5460649061ffff1661338f87612397565b6133999190615812565b6133a3919061583a565b6133ab565b60005b878a611693565b905080886004015489600301546133c991906150eb565b10156133e85760405163444a5eaf60e11b815260040160405180910390fd5b808860040160008282546133fc919061518b565b90915550506000878152600589016020526040902081905591505095945050505050565b600054610100900460ff166134475760405162461bcd60e51b8152600401610b359061585d565b610d6761431c565b60405162f577a560e81b8152600481018390526060907334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca89063f577a50090602401602060405180830381865af41580156134a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c591906158b3565b6134e257604051638529df1f60e01b815260040160405180910390fd5b815160000361350457604051638bdcc37560e01b815260040160405180910390fd5b60c9546040516333ad819560e21b8152600481018890526000916001600160a01b03169063ceb6065490602401600060405180830381865afa15801561354e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135769190810190615b60565b90506135868160a001513361434c565b6135a35760405163d9ce719d60e01b815260040160405180910390fd5b60408051602081018890528082018790528151808203830181526060820192839052633033cc5160e01b9092526000907334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca890633033cc51906135fd908590606401615c65565b6040805180830381865af4158015613619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061363d9190615c78565b90507334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca863ebbdac917334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca86313bc64ee896040518263ffffffff1660e01b815260040161369291815260200190565b6040805180830381865af41580156136ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d29190615c78565b856101000151846040518463ffffffff1660e01b81526004016136f793929190615d1e565b602060405180830381865af4158015613714573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061373891906158b3565b61375557604051638baa579f60e01b815260040160405180910390fd5b600085516001600160401b03811115613770576137706147dd565b6040519080825280602002602001820160405280156137a957816020015b61379661476f565b81526020019060019003908161378e5790505b509050600086516001600160401b038111156137c7576137c76147dd565b60405190808252806020026020018201604052801561380057816020015b6137ed61478d565b8152602001906001900390816137e55790505b50905086516001600160401b0381111561381c5761381c6147dd565b604051908082528060200260200182016040528015613845578160200160208202803683370190505b50955060005b8751811015613a92577334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca863f577a50089838151811061388057613880614fe7565b6020026020010151602001516040518263ffffffff1660e01b81526004016138aa91815260200190565b602060405180830381865af41580156138c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138eb91906158b3565b61390857604051636b849b7d60e11b815260040160405180910390fd5b7334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca86313bc64ee89838151811061393457613934614fe7565b6020026020010151602001516040518263ffffffff1660e01b815260040161395e91815260200190565b6040805180830381865af415801561397a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061399e9190615c78565b8382815181106139b0576139b0614fe7565b602002602001018190525085608001518882815181106139d2576139d2614fe7565b602002602001015160000151815181106139ee576139ee614fe7565b602002602001015160200151828281518110613a0c57613a0c614fe7565b60200260200101819052508560800151888281518110613a2e57613a2e614fe7565b60200260200101516000015181518110613a4a57613a4a614fe7565b602002602001015160000151878281518110613a6857613a68614fe7565b6001600160a01b039092166020928302919091019091015280613a8a81615013565b91505061384b565b50604051630d6870d760e21b81527334e6885e0e9bbea0bae36d00d4d9b4ed873f2ca8906335a1c35c90613ace90859085908890600401615d47565b602060405180830381865af4158015613aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0f91906158b3565b613b2c57604051639c2d1c6d60e01b815260040160405180910390fd5b505050505095945050505050565b60008060608184604001516002811115613b5657613b56615295565b03613ba05750604080516024810187905260448082018790528251808303909101815260649091019091526020810180516001600160e01b03166394985ddd60e01b179052613d8a565b600184604001516002811115613bb857613bb8615295565b03613ceb5760008460600151806020019051810190613bd79190615ddd565b905060008163ffffffff166001600160401b03811115613bf957613bf96147dd565b604051908082528060200260200182016040528015613c22578160200160208202803683370190505b50905060005b8263ffffffff16811015613c925760408051602081018a90529081018290526060016040516020818303038152906040528051906020012060001c828281518110613c7557613c75614fe7565b602090810291909101015280613c8a81615013565b915050613c28565b506040516375bf929b60e01b90613caf908a908490602401615dfa565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529250613d8a915050565b600284604001516002811115613d0357613d03615295565b03613d8a5760008460600151806020019051810190613d229190615ddd565b90506000613d368263ffffffff16886143a7565b9050639e5836f660e01b8882604051602401613d53929190615dfa565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152925050505b60d0805466ff0000000000001916600160301b17905560e08401516080850151613dbb9163ffffffff169083614502565b60d0805466ff000000000000191690559695505050505050565b6006840180546000918291600191908390613dfa9084906001600160401b03166150c4565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550600060d960010160029054906101000a900460ff1615613e4c575060068601546001600160401b0316613f03565b60db544210801590613e60575060dc544211155b15613f035760db5460078801541015613ea05760068701805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b179055613eec565b60018760060160188282829054906101000a90046001600160401b0316613ec791906150c4565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b506006860154600160c01b90046001600160401b03165b4260078801556006870154600090600160401b90046001600160401b031615613f765760018860060160088282829054906101000a90046001600160401b0316613f4d9190615e3b565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550613fb5565b60da5460649061ffff16613f8984612397565b613f9e9063ffffffff1664e8d4a5100061512d565b613fa8919061512d565b613fb2919061515a565b90505b6000613fe886613fc78961232861512d565b60d054613fe19190600160381b900463ffffffff1661518b565b843a61454e565b9050808960030154101561400f5760405163964d765f60e01b815260040160405180910390fd5b600088815260058a01602052604081205460048b018054919290916140359084906150eb565b9091555050600088815260058a016020526040812081905560038a0180548392906140619084906150eb565b925050819055508160ca600082825461407a919061518b565b909155509099919850909650505050505050565b60d35460cb80546000906140a390849061518b565b9091555050825160d2546140b7919061512d565b60cc60008282546140c8919061518b565b909155505060408051600180825281830190925260009160208083019080368337019050509050338160008151811061410357614103614fe7565b6001600160a01b03928316602091820292909201015260c9541663914eb34d8261412d85876150eb565b60d3546040516001600160e01b031960e086901b16815261415393929190600401615e5b565b600060405180830381600087803b15801561416d57600080fd5b505af1158015614181573d6000803e3d6000fd5b505060c95486516001600160a01b03909116925063914eb34d915086906141a8908661515a565b60d2546040516001600160e01b031960e086901b1681526141ce93929190600401615e5b565b600060405180830381600087803b1580156141e857600080fd5b505af11580156141fc573d6000803e3d6000fd5b5050505050505050565b6001600160a01b0381163b6142735760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b35565b600080516020615eb483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6142ab836145fd565b6000825111806142b85750805b15610a875761107a838361463d565b6000805b835181101561431057828482815181106142e7576142e7614fe7565b6020026020010151036142fe576001915050614316565b8061430881615013565b9150506142cb565b50600090505b92915050565b600054610100900460ff166143435760405162461bcd60e51b8152600401610b359061585d565b610d6733613046565b6000805b835181101561431057826001600160a01b031684828151811061437557614375614fe7565b60200260200101516001600160a01b031603614395576001915050614316565b8061439f81615013565b915050614350565b60606000836001600160401b038111156143c3576143c36147dd565b6040519080825280602002602001820160405280156143ec578160200160208202803683370190505b50905060005b8481101561442a578082828151811061440d5761440d614fe7565b60209081029190910101528061442281615013565b9150506143f2565b5080516000805b600061443c84615e80565b93508311156144f75761444f83876157e1565b91508560405160200161446491815260200190565b6040516020818303038152906040528051906020012060001c955083838151811061449157614491614fe7565b602002602001015190508382815181106144ad576144ad614fe7565b60200260200101518484815181106144c7576144c7614fe7565b602002602001018181525050808483815181106144e6576144e6614fe7565b602002602001018181525050614431565b509195945050505050565b60005a61138881101561451457600080fd5b61138881039050846040820482031161452c57600080fd5b50823b61453857600080fd5b60008083516020850160008789f1949350505050565b600080738ffe9b19591b031c7b76a27d1b356ed0a8441b8063c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865af415801561459a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145be9190615114565b5a6145c9888861518b565b6145d391906150eb565b6145dd908561512d565b6145e7919061518b565b90506145f3848261518b565b9695505050505050565b61460681614206565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6146a55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b35565b600080846001600160a01b0316846040516146c09190615e97565b600060405180830381855af49150503d80600081146146fb576040519150601f19603f3d011682016040523d82523d6000602084013e614700565b606091505b50915091506147288282604051806060016040528060278152602001615ed460279139614731565b95945050505050565b60608315614740575081613202565b61320283838151156147555781518083602001fd5b8060405162461bcd60e51b8152600401610b359190615c65565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b80356001600160401b0381168114611cf857600080fd5b6000602082840312156147d457600080fd5b613202826147ab565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715614816576148166147dd565b60405290565b60405160e081016001600160401b0381118282101715614816576148166147dd565b604080519081016001600160401b0381118282101715614816576148166147dd565b60405161014081016001600160401b0381118282101715614816576148166147dd565b604051606081016001600160401b0381118282101715614816576148166147dd565b604051601f8201601f191681016001600160401b03811182821017156148cd576148cd6147dd565b604052919050565b60006001600160401b038211156148ee576148ee6147dd565b5060051b60200190565b600082601f83011261490957600080fd5b8135602061491e614919836148d5565b6148a5565b82815260059290921b8401810191818101908684111561493d57600080fd5b8286015b8481101561495f57614952816147ab565b8352918301918301614941565b509695505050505050565b6000806040838503121561497d57600080fd5b82356001600160401b038082111561499457600080fd5b6149a0868387016148f8565b935060208501359150808211156149b657600080fd5b506149c3858286016148f8565b9150509250929050565b6001600160a01b03811681146109de57600080fd5b8035611cf8816149cd565b60008060408385031215614a0057600080fd5b8235614a0b816149cd565b946020939093013593505050565b600060208284031215614a2b57600080fd5b5035919050565b600060208284031215614a4457600080fd5b8135613202816149cd565b600082601f830112614a6057600080fd5b81356001600160401b03811115614a7957614a796147dd565b614a8c601f8201601f19166020016148a5565b818152846020838601011115614aa157600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614ad157600080fd5b8235614adc816149cd565b915060208301356001600160401b03811115614af757600080fd5b6149c385828601614a4f565b803561ffff81168114611cf857600080fd5b63ffffffff811681146109de57600080fd5b8035611cf881614b15565b600080600080600080600060e0888a031215614b4d57600080fd5b614b5688614b03565b96506020880135614b6681614b15565b95506040880135614b7681614b15565b94506060880135614b8681614b15565b9699959850939660808101359560a0820135955060c0909101359350915050565b60008060408385031215614bba57600080fd5b614bc3836147ab565b91506020830135614bd3816149cd565b809150509250929050565b60008060408385031215614bf157600080fd5b614bfa836147ab565b9150614c08602084016147ab565b90509250929050565b600080600080600060a08688031215614c2957600080fd5b8535614c3481614b15565b94506020860135614c4481614b15565b93506040860135614c5481614b15565b9250606086013591506080860135614c6b81614b15565b809150509295509295909350565b600060208284031215614c8b57600080fd5b81356001600160401b03811115614ca157600080fd5b820160e0818503121561320257600080fd5b600081518084526020808501945080840160005b83811015614cec5781516001600160a01b031687529582019590820190600101614cc7565b509495945050505050565b60006101206001600160a01b038c168352806020840152614d1a8184018c614cb3565b604084019a909a52505060608101969096526001600160401b03948516608087015292841660a086015290831660c085015290911660e08301526101009091015292915050565b60006101408284031215614d7457600080fd5b50919050565b60008060008060008060a08789031215614d9357600080fd5b8635614d9e81614b15565b9550602087013594506040870135935060608701356001600160401b0380821115614dc857600080fd5b614dd48a838b01614d61565b94506080890135915080821115614dea57600080fd5b818901915089601f830112614dfe57600080fd5b813581811115614e0d57600080fd5b8a60208260061b8501011115614e2257600080fd5b6020830194508093505050509295509295509295565b60008060408385031215614e4b57600080fd5b8235915060208301356001600160401b03811115614e6857600080fd5b6149c385828601614d61565b80151581146109de57600080fd5b8035611cf881614e74565b600080600060608486031215614ea257600080fd5b8335614ead81614e74565b9250614ebb60208501614b03565b9150614ec960408501614b03565b90509250925092565b803562ffffff81168114611cf857600080fd5b60008060008060008587036101a0811215614eff57600080fd5b61012080821215614f0f57600080fd5b614f176147f3565b9150614f2288614b27565b8252614f3060208901614b27565b6020830152614f4160408901614b27565b6040830152614f5260608901614b27565b6060830152614f6360808901614b27565b6080830152614f7460a08901614ed2565b60a0830152614f8560c08901614ed2565b60c0830152614f9660e08901614ed2565b60e0830152610100614fa9818a01614ed2565b8184015250819650614fbc818901614b03565b95505050614fcd6101408701614e82565b949793965093946101608101359450610180013592915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161502557615025614ffd565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6001600160401b038181168382160190808211156150e4576150e4614ffd565b5092915050565b8181038181111561431657614316614ffd565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561512657600080fd5b5051919050565b808202811582820484141761431657614316614ffd565b634e487b7160e01b600052601260045260246000fd5b60008261516957615169615144565b500490565b63ffffffff8181168382160190808211156150e4576150e4614ffd565b8082018082111561431657614316614ffd565b60006001600160401b038083168181036151ba576151ba614ffd565b6001019392505050565b803560038110611cf857600080fd5b600060e082360312156151e557600080fd5b6151ed61481c565b6151f6836151c4565b815260208301356001600160401b0381111561521157600080fd5b61521d36828601614a4f565b60208301525061522f604084016147ab565b60408201526060830135606082015261524a60808401614b03565b608082015261525b60a08401614b27565b60a082015260c092830135928101929092525090565b6000806040838503121561528457600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fd5b600381106152c957634e487b7160e01b600052602160045260246000fd5b9052565b60005b838110156152e85781810151838201526020016152d0565b50506000910152565b600081518084526153098160208601602086016152cd565b601f01601f19169290920160200192915050565b60006101608d83526001600160401b038d16602084015263ffffffff808d16604085015261534e606085018d6152ab565b8160808501526153608285018c6152f1565b6001600160a01b039a909a1660a085015260c0840198909852505061ffff9490941660e085015291909316610100830152610120820192909252610140015295945050505050565b60006101006153b7838c6152ab565b8060208401526153c98184018b6152f1565b6001600160a01b039990991660408401525050606081019590955261ffff93909316608085015263ffffffff9190911660a084015260c083015260e09091015292915050565b60006020828403121561542157600080fd5b813561320281614b15565b60006020828403121561543e57600080fd5b613202826151c4565b6000808335601e1984360301811261545e57600080fd5b8301803591506001600160401b0382111561547857600080fd5b60200191503681900382131561548d57600080fd5b9250929050565b6000602082840312156154a657600080fd5b61320282614b03565b60006101608e83526001600160401b038e16602084015263ffffffff8d1660408401526154df606084018d6152ab565b806080840152898184015250610180898b8285013760008a84018201526001600160a01b03891660a0840152601f19601f8b011683010190508660c083015261552e60e083018761ffff169052565b63ffffffff851661010083015261012082019390935261014001529a9950505050505050505050565b60006040828403121561556957600080fd5b61557161483e565b82358152602083013560208201528091505092915050565b6000610140823603121561559c57600080fd5b6155a4614860565b6155ad836147ab565b81526155bb60208401614b27565b60208201526155cc604084016151c4565b604082015260608301356001600160401b038111156155ea57600080fd5b6155f636828601614a4f565b606083015250615608608084016149e2565b608082015260a083013560a082015261562360c08401614b03565b60c082015261563460e08401614b27565b60e0820152610100838101359082015261012092830135928101929092525090565b60a08152600061566960a0830188614cb3565b905085602083015284604083015283606083015282151560808301529695505050505050565b855163ffffffff9081168252602080880151821690830152604080880151821690830152606080880151821690830152608080880151918216908301526101a08201905060a08701516156e960a084018262ffffff169052565b5060c087015161570060c084018262ffffff169052565b5060e087015161571760e084018262ffffff169052565b506101009687015162ffffff169682019690965261ffff949094166101208501529115156101408401526101608301526101809091015290565b6000602080838503121561576457600080fd5b82516001600160401b0381111561577a57600080fd5b8301601f8101851361578b57600080fd5b8051615799614919826148d5565b81815260059190911b820183019083810190878311156157b857600080fd5b928401925b828410156157d6578351825292840192908401906157bd565b979650505050505050565b6000826157f0576157f0615144565b500690565b63ffffffff8281168282160390808211156150e4576150e4614ffd565b63ffffffff81811683821602808216919082811461583257615832614ffd565b505092915050565b600063ffffffff8084168061585157615851615144565b92169190910492915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8051611cf881614e74565b6000602082840312156158c557600080fd5b815161320281614e74565b600082601f8301126158e157600080fd5b604051608081018181106001600160401b0382111715615903576159036147dd565b60405280608084018581111561591857600080fd5b845b818110156144f757805183526020928301920161591a565b600082601f83011261594357600080fd5b81516020615953614919836148d5565b82815260a0928302850182019282820191908785111561597257600080fd5b8387015b858110156159c05781818a03121561598e5760008081fd5b61599661483e565b81516159a1816149cd565b81526159af8a8388016158d0565b818701528452928401928101615976565b5090979650505050505050565b600082601f8301126159de57600080fd5b815160206159ee614919836148d5565b82815260059290921b84018101918181019086841115615a0d57600080fd5b8286015b8481101561495f578051615a24816149cd565b8352918301918301615a11565b600082601f830112615a4257600080fd5b81516020615a52614919836148d5565b82815260059290921b84018101918181019086841115615a7157600080fd5b8286015b8481101561495f5780516001600160401b0380821115615a9457600080fd5b908801906040601f19838c038101821315615aae57600080fd5b615ab661483e565b8885015184811115615ac757600080fd5b615ad58e8b838901016159cd565b8252508285015184811115615ae957600080fd5b949094019360c0858e0383011215615b015760008081fd5b615b09614883565b9150888501518252615b1d8d8487016158d0565b8983015260c085015184811115615b345760008081fd5b615b428e8b838901016159cd565b93830193909352808901919091528652505050918301918301615a75565b600060208284031215615b7257600080fd5b81516001600160401b0380821115615b8957600080fd5b908301906101808286031215615b9e57600080fd5b615ba66147f3565b82518152602083015160208201526040830151604082015260608301516060820152608083015182811115615bda57600080fd5b615be687828601615932565b60808301525060a083015182811115615bfe57600080fd5b615c0a878286016159cd565b60a08301525060c083015182811115615c2257600080fd5b615c2e87828601615a31565b60c083015250615c4060e084016158a8565b60e08201526101009150615c56868385016158d0565b91810191909152949350505050565b60208152600061320260208301846152f1565b600060408284031215615c8a57600080fd5b82601f830112615c9957600080fd5b615ca161483e565b806040840185811115615cb357600080fd5b845b81811015615ccd578051845260209384019301615cb5565b509095945050505050565b8060005b600281101561107a578151845260209384019390910190600101615cdc565b8060005b600481101561107a578151845260209384019390910190600101615cff565b6101008101615d2d8286615cd8565b615d3a6040830185615cfb565b61326060c0830184615cd8565b608080825284518282018190526000919060209060a0850190828901855b82811015615d8b57615d78848351615cd8565b6040939093019290840190600101615d65565b5050508481038286015286518082528783019183019060005b81811015615dc757615db7838551615cfb565b9284019291850191600101615da4565b5050809450505050506132606040830184615cd8565b600060208284031215615def57600080fd5b815161320281614b15565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156159c057845183529383019391830191600101615e1f565b6001600160401b038281168282160390808211156150e4576150e4614ffd565b606081526000615e6e6060830186614cb3565b60208301949094525060400152919050565b600081615e8f57615e8f614ffd565b506000190190565b60008251615ea98184602087016152cd565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c8bc09fbba0404d1748ce032f33b2c531725d05734c46b60697551ef575283be64736f6c63430008120033
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.