Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EOFeedVerifier
Compiler Version
v0.8.25+commit.b61c2a91
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { IEOFeedVerifier } from "./interfaces/IEOFeedVerifier.sol";
import { IBLS } from "./interfaces/IBLS.sol";
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
// solhint-disable no-unused-import
import {
CallerIsNotFeedManager,
InvalidProof,
InvalidInput,
InvalidAddress,
InvalidEventRoot,
VotingPowerIsZero,
InsufficientVotingPower,
SignatureVerificationFailed,
SignaturePairingFailed,
ValidatorIndexOutOfBounds,
ValidatorSetTooSmall,
DuplicatedAddresses
} from "./interfaces/Errors.sol";
/**
* @title EOFeedVerifier
* @author eOracle
* @notice The EOFeedVerifier contract handles the verification of update payloads. The payload includes a Merkle root
* signed by eoracle validators and a Merkle path to the leaf containing the data. The verifier stores the current
* validator set in its storage and ensures that the Merkle root is signed by a subset of this validator set with
* sufficient voting power.
*/
contract EOFeedVerifier is IEOFeedVerifier, OwnableUpgradeable {
bytes32 public constant DOMAIN = keccak256("EORACLE_FEED_VERIFIER");
uint256 public constant MIN_VALIDATORS = 3;
/// @dev BLS library contract
IBLS internal _bls;
/// @dev length of validators set
uint256 internal _currentValidatorSetLength;
/// @dev total voting power of the current validators set
uint256 internal _totalVotingPower;
/// @dev current validators set (index => Validator)
mapping(uint256 => Validator) internal _currentValidatorSet;
/// @dev hash (keccak256) of the current validator set
bytes32 internal _currentValidatorSetHash;
/// @dev block number of the last processed block
uint256 internal _lastProcessedBlockNumber;
/// @dev event root of the last processed block
bytes32 internal _lastProcessedEventRoot;
/// @dev address of the feed manager
address internal _feedManager;
/// @dev full apk of the current validator set
uint256[2] internal _fullApk;
/* ============ Modifiers ============ */
/**
* @dev Allows only the feed manager to call the function
*/
modifier onlyFeedManager() {
if (msg.sender != _feedManager) revert CallerIsNotFeedManager();
_;
}
/* ============ Constructor ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/* ============ Initializer ============ */
/**
* @param owner Owner of the contract
*/
function initialize(address owner, IBLS bls_) external initializer {
if (address(bls_) == address(0) || address(bls_).code.length == 0) {
revert InvalidAddress();
}
_bls = bls_;
__Ownable_init(owner);
}
/* ============ External Functions ============ */
/**
* @inheritdoc IEOFeedVerifier
*/
function verify(
LeafInput calldata input,
VerificationParams calldata vParams
)
external
onlyFeedManager
returns (bytes memory)
{
_verifyParams(vParams);
bytes memory data = _verifyLeaf(input, vParams.eventRoot);
return data;
}
/**
* @inheritdoc IEOFeedVerifier
*/
function batchVerify(
LeafInput[] calldata inputs,
VerificationParams calldata vParams
)
external
onlyFeedManager
returns (bytes[] memory)
{
_verifyParams(vParams);
return _verifyLeaves(inputs, vParams.eventRoot);
}
/**
* @notice Function to set a new validator set
* @param newValidatorSet The new validator set to store
*/
function setNewValidatorSet(Validator[] calldata newValidatorSet) external onlyOwner {
uint256 length = newValidatorSet.length;
if (length < MIN_VALIDATORS) revert ValidatorSetTooSmall();
if (!_hasNoAddressDuplicates(newValidatorSet)) revert DuplicatedAddresses();
if (length < _currentValidatorSetLength) {
for (uint256 i = length; i < _currentValidatorSetLength; i++) {
// slither-disable-next-line costly-loop
delete _currentValidatorSet[i];
}
}
_currentValidatorSetLength = length;
_currentValidatorSetHash = keccak256(abi.encode(newValidatorSet));
uint256 totalPower = 0;
uint256[2] memory apk = [uint256(0), uint256(0)];
for (uint256 i = 0; i < length; i++) {
if (newValidatorSet[i]._address == address(0)) revert InvalidAddress();
uint256 votingPower = newValidatorSet[i].votingPower;
if (votingPower == 0) revert VotingPowerIsZero();
totalPower += votingPower;
_currentValidatorSet[i] = newValidatorSet[i];
// slither-disable-next-line calls-loop
apk = _bls.ecadd(apk, newValidatorSet[i].g1pk);
}
_fullApk = apk;
_totalVotingPower = totalPower;
emit ValidatorSetUpdated(_currentValidatorSetLength, _currentValidatorSetHash, _totalVotingPower);
}
/**
* @notice Sets the address of the feed manager.
* @param feedManager_ The address of the new feed manager.
*/
function setFeedManager(address feedManager_) external onlyOwner {
if (feedManager_ == address(0)) revert InvalidAddress();
_feedManager = feedManager_;
emit FeedManagerSet(feedManager_);
}
/**
* @notice Set the BLS contract
* @param bls_ Address of the BLS contract
*/
function setBLS(IBLS bls_) external onlyOwner {
if (address(bls_) == address(0) || address(bls_).code.length == 0) {
revert InvalidAddress();
}
_bls = bls_;
}
/**
* @notice Returns the length of the current validator set.
* @return The number of validators in the current set.
*/
function currentValidatorSetLength() external view returns (uint256) {
return _currentValidatorSetLength;
}
/**
* @notice Returns the total voting power of the current validator set.
* @return The total voting power.
*/
function totalVotingPower() external view returns (uint256) {
return _totalVotingPower;
}
/**
* @notice Returns the validator at the specified index in the current validator set.
* @param index The index of the validator in the current set.
* @return The validator at the given index.
*/
function currentValidatorSet(uint256 index) external view returns (Validator memory) {
if (index >= _currentValidatorSetLength) revert ValidatorIndexOutOfBounds();
return _currentValidatorSet[index];
}
/**
* @notice Returns the hash of the current validator set.
* @return The hash of the current validator set.
*/
function currentValidatorSetHash() external view returns (bytes32) {
return _currentValidatorSetHash;
}
/**
* @notice Returns the block number of the last processed block.
* @return The last processed block number.
*/
function lastProcessedBlockNumber() external view returns (uint256) {
return _lastProcessedBlockNumber;
}
/**
* @notice Returns the event root of the last processed block.
* @return The last processed event root.
*/
function lastProcessedEventRoot() external view returns (bytes32) {
return _lastProcessedEventRoot;
}
/**
* @notice Returns the address of the feed manager.
* @return The address of the feed manager.
*/
function feedManager() external view returns (address) {
return _feedManager;
}
function bls() external view returns (IBLS) {
return _bls;
}
/* ============ Internal Functions ============ */
/**
* @notice Function to verify the checkpoint signature
* @param vParams Signed data
*/
function _verifyParams(IEOFeedVerifier.VerificationParams calldata vParams) internal {
// if the eventRoot has not changed, we don't need to verify the whole checkpoint again
if (vParams.eventRoot == _lastProcessedEventRoot) {
return;
}
bytes32 msgHash = keccak256(
abi.encode(vParams.eventRoot, vParams.blockNumber, vParams.blockHash, vParams.chainId, vParams.aggregator)
);
if (vParams.eventRoot == bytes32(0)) revert InvalidEventRoot();
_verifySignature(msgHash, vParams.signature, vParams.apkG2, vParams.nonSignersBitmap);
if (vParams.blockNumber > _lastProcessedBlockNumber) {
_lastProcessedBlockNumber = vParams.blockNumber;
_lastProcessedEventRoot = vParams.eventRoot;
}
}
/**
* @notice Verify the signature of the checkpoint
* @param messageHash Hash of the message to verify
* @param signature G1 Aggregated signature of the checkpoint
* @param apkG2 G2 Aggregated public key of the checkpoint
* @param nonSignersBitmap Bitmap of the validators who did not sign the data
*/
function _verifySignature(
bytes32 messageHash,
uint256[2] calldata signature,
uint256[4] calldata apkG2,
bytes calldata nonSignersBitmap
)
internal
view
{
uint256[2] memory apk = [uint256(0), uint256(0)];
uint256 aggVotingPower = _totalVotingPower;
// first apk will hold all non signers
for (uint256 i = 0; i < _currentValidatorSetLength; i++) {
Validator memory v = _currentValidatorSet[i];
if (_getValueFromBitmap(nonSignersBitmap, i)) {
apk = _bls.ecadd(apk, v.g1pk);
aggVotingPower -= v.votingPower;
}
}
// we check the agg voting power is indeed sufficient
if (aggVotingPower <= ((2 * _totalVotingPower) / 3)) revert InsufficientVotingPower();
// then we negate the non signers and add the full apk
apk = _bls.ecadd(_fullApk, _bls.neg(apk));
uint256[2] memory hashPoint = _bls.hashToPoint(DOMAIN, abi.encodePacked(messageHash));
(bool pairingSuccessful, bool signatureIsValid) =
_bls.verifySignatureAndVeracity(apk, signature, hashPoint, apkG2);
if (!pairingSuccessful) revert SignaturePairingFailed();
if (!signatureIsValid) revert SignatureVerificationFailed();
}
/**
* @notice Verify a batch of exits leaves
* @param inputs Batch exit inputs for multiple event leaves
* @param eventRoot the root this event should belong to
* @return Array of the unhashed leaves
*/
function _verifyLeaves(LeafInput[] calldata inputs, bytes32 eventRoot) internal pure returns (bytes[] memory) {
if (inputs.length == 0) revert InvalidInput();
uint256 length = inputs.length;
bytes[] memory returnData = new bytes[](length);
for (uint256 i = 0; i < length; i++) {
returnData[i] = _verifyLeaf(inputs[i], eventRoot);
}
return returnData;
}
/**
* @notice Verify for one event
* @param input Exit leaf input
* @param eventRoot event root the leaf should belong to
* @return The unhashed leaf
*/
function _verifyLeaf(LeafInput calldata input, bytes32 eventRoot) internal pure returns (bytes memory) {
bytes32 leaf = keccak256(input.unhashedLeaf);
if (!MerkleProof.verify(input.proof, eventRoot, leaf)) {
revert InvalidProof();
}
return input.unhashedLeaf;
}
/**
* @dev Extracts a boolean value from a specific index in a bitmap.
* @param bitmap The bytes array containing the bitmap.
* @param index The bit position from which to retrieve the value.
* @return bool The boolean value of the bit at the specified index in the bitmap.
* Returns 'true' if the bit is set (1), and 'false' if the bit is not set (0).
*/
function _getValueFromBitmap(bytes calldata bitmap, uint256 index) private pure returns (bool) {
uint256 byteNumber = index / 8;
// safe to downcast as any value % 8 will always be less than 8
uint8 bitNumber = uint8(index % 8);
if (byteNumber >= bitmap.length) {
return false;
}
// safe to downcast as bitmap[byteNumber] is byte and less than 256
return uint8(bitmap[byteNumber]) & (1 << bitNumber) > 0;
}
/**
* @dev Checks if there are no duplicate addresses in the validator set.
* @param validators The array of validators to check for duplicates.
* @return bool True if there are no duplicate addresses, false otherwise.
*/
function _hasNoAddressDuplicates(Validator[] calldata validators) private pure returns (bool) {
for (uint256 i = 0; i < validators.length; i++) {
for (uint256 j = i + 1; j < validators.length; j++) {
if (validators[i]._address == validators[j]._address) {
return false;
}
}
}
return true;
}
/**
* @dev Gap for future storage variables in upgradeable contract.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
// solhint-disable ordering
// slither-disable-next-line unused-state,naming-convention
uint256[50] private __gap;
// solhint-disable enable
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
/**
* @title IEOFeedVerifier
* @author eOracle
*/
interface IEOFeedVerifier {
/* ============ Structs ============ */
/**
* @dev Input data for leaf verification
* @param leafIndex Index of the leaf
* @param unhashedLeaf Unhashed leaf data
* abi encoded (uint256 feedId, uint256 rate, uint256 timestamp)
* @param proof Merkle proof of the leaf
*/
struct LeafInput {
uint256 leafIndex;
bytes unhashedLeaf;
bytes32[] proof;
}
/**
* @dev Signed Data structure
* @param eventRoot merkle tree root for events
* @param blockNumber the block number this merkle tree originated from (on EO chain)
* @param signature G1 hashed payload of abi.encode(eventRoot, blockNumber)
* @param apkG2 G2 apk provided from off-chain
* @param nonSignersBitmap used to construct G1 apk onchain
*/
struct VerificationParams {
uint64 blockNumber; // 8 bytes +
uint32 chainId; // 4 bytes +
address aggregator; // 20 bytes = 32 bytes
bytes32 eventRoot; // 32 bytes
bytes32 blockHash; // 32 bytes
uint256[2] signature; // 64 bytes
uint256[4] apkG2; // 128 bytes
bytes nonSignersBitmap; // dynamic
}
/**
* @notice Represents a validator in the system
* @param _address The validator's address
* @param g1pk validator G1 public key
* @param g2pk validator G2 public key (not used in current implementation)
* @param votingPower Validator voting power
*/
struct Validator {
address _address;
uint256[2] g1pk;
uint256[4] g2pk;
uint256 votingPower;
}
/* ============ Events ============ */
/**
* @dev Event emitted when the validator set is updated
* @param currentValidatorSetLength Length of the current validator set
* @param currentValidatorSetHash Hash of the current validator set
* @param totalVotingPower Total voting power of the current validator set
*/
event ValidatorSetUpdated(
uint256 currentValidatorSetLength, bytes32 currentValidatorSetHash, uint256 totalVotingPower
);
/**
* @dev Event emitted when the feed manager is set
* @param feedManager Address of the feed manager
*/
event FeedManagerSet(address feedManager);
/* ============ External Functions ============ */
/**
* @notice verify single leaf signature from a block merkle tree
* @param input leaf input data and proof (LeafInput)
* @param vParams verification params
* @return leafData Leaf data, abi encoded (uint256 feedId, uint256 rate, uint256 timestamp)
*/
function verify(
LeafInput memory input,
VerificationParams calldata vParams
)
external
returns (bytes memory leafData);
/**
* @notice batch verify signature of multiple leaves from the same block merkle tree
* @param inputs feed leaves
* @param vParams verification params
*/
function batchVerify(
LeafInput[] memory inputs,
VerificationParams calldata vParams
)
external
returns (bytes[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
interface IBLS {
/**
* @notice hashes an arbitrary message to a point on the curve
* @dev Fouque-Tibouchi Hash to Curve
* @param domain domain separator for the hash
* @param message the message to map
* @return uint256[2] (x,y) point on the curve that the message maps to
*/
function hashToPoint(bytes32 domain, bytes memory message) external view returns (uint256[2] memory);
/**
* @notice verifies a single signature
* @param signature 64-byte G1 group element (small sig)
* @param pubkey 128-byte G2 group element (big pubkey)
* @param message message signed to produce signature
* @return bool sig verification
* @return bool indicating call success
*/
function verifySignature(
uint256[2] calldata signature,
uint256[4] calldata pubkey,
uint256[2] calldata message
)
external
view
returns (bool, bool);
/**
* @notice verifies a single signature and the veracity of the apk
* @param pubkey 64-byte G1 group element (small pubkey) - the claimed G1 pubkey
* @param signature 64-byte G1 group element (small sig)
* @param message hash 64-byte message signed to produce signature
* @param pubkeyG2 128-byte G2 group element (big apk) - the provided G2 pubkey
* @return bool sig verification
* @return bool indicating call success
*/
function verifySignatureAndVeracity(
uint256[2] calldata pubkey,
uint256[2] calldata signature,
uint256[2] calldata message,
uint256[4] calldata pubkeyG2
)
external
view
returns (bool, bool);
function ecadd(uint256[2] calldata a, uint256[2] calldata b) external view returns (uint256[2] memory);
function ecmul(uint256[2] calldata p, uint256 s) external view returns (uint256[2] memory);
function neg(uint256[2] calldata a) external pure returns (uint256[2] memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.20;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the Merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates Merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
*@dev The multiproof provided is not valid.
*/
error MerkleProofInvalidMultiproof();
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Sorts the pair (a, b) and hashes the result.
*/
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
/*//////////////////////////////////////////////////////////////////////////
EOFeedManager
//////////////////////////////////////////////////////////////////////////*/
error CallerIsNotWhitelisted(address caller);
error MissingLeafInputs();
error FeedNotSupported(uint256 feedId);
error CallerIsNotPauser();
error CallerIsNotUnpauser();
error CallerIsNotFeedDeployer();
/*//////////////////////////////////////////////////////////////////////////
EOFeedVerifier
//////////////////////////////////////////////////////////////////////////*/
error CallerIsNotFeedManager();
error InvalidInput();
error InvalidProof();
error InvalidAddress();
error InvalidEventRoot();
error VotingPowerIsZero();
error InsufficientVotingPower();
error SignatureVerificationFailed();
error SignaturePairingFailed();
error ValidatorIndexOutOfBounds();
error ValidatorSetTooSmall();
error DuplicatedAddresses();
/*//////////////////////////////////////////////////////////////////////////
EOFeedRegistryAdapter
//////////////////////////////////////////////////////////////////////////*/
error FeedAlreadyExists();
error BaseQuotePairExists();
error FeedDoesNotExist();
error NotFeedDeployer();// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"ds-test/=lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"forge-safe/=lib/forge-safe/src/",
"eigenlayer-contracts/=lib/eigenlayer-contracts/src/contracts/",
"@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/",
"@openzeppelin-upgrades/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/",
"@openzeppelin-v4.9.0/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts-v4.9.0/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/",
"openzeppelin/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/",
"solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
"solmate/=lib/forge-safe/lib/solmate/src/",
"surl/=lib/forge-safe/lib/surl/",
"zeus-templates/=lib/eigenlayer-contracts/lib/zeus-templates/src/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerIsNotFeedManager","type":"error"},{"inputs":[],"name":"DuplicatedAddresses","type":"error"},{"inputs":[],"name":"InsufficientVotingPower","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidEventRoot","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SignaturePairingFailed","type":"error"},{"inputs":[],"name":"SignatureVerificationFailed","type":"error"},{"inputs":[],"name":"ValidatorIndexOutOfBounds","type":"error"},{"inputs":[],"name":"ValidatorSetTooSmall","type":"error"},{"inputs":[],"name":"VotingPowerIsZero","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feedManager","type":"address"}],"name":"FeedManagerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":false,"internalType":"uint256","name":"currentValidatorSetLength","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"currentValidatorSetHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalVotingPower","type":"uint256"}],"name":"ValidatorSetUpdated","type":"event"},{"inputs":[],"name":"DOMAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"leafIndex","type":"uint256"},{"internalType":"bytes","name":"unhashedLeaf","type":"bytes"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct IEOFeedVerifier.LeafInput[]","name":"inputs","type":"tuple[]"},{"components":[{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"bytes32","name":"eventRoot","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"uint256[4]","name":"apkG2","type":"uint256[4]"},{"internalType":"bytes","name":"nonSignersBitmap","type":"bytes"}],"internalType":"struct IEOFeedVerifier.VerificationParams","name":"vParams","type":"tuple"}],"name":"batchVerify","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bls","outputs":[{"internalType":"contract IBLS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"currentValidatorSet","outputs":[{"components":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256[2]","name":"g1pk","type":"uint256[2]"},{"internalType":"uint256[4]","name":"g2pk","type":"uint256[4]"},{"internalType":"uint256","name":"votingPower","type":"uint256"}],"internalType":"struct IEOFeedVerifier.Validator","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentValidatorSetHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentValidatorSetLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feedManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract IBLS","name":"bls_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastProcessedBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastProcessedEventRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IBLS","name":"bls_","type":"address"}],"name":"setBLS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feedManager_","type":"address"}],"name":"setFeedManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256[2]","name":"g1pk","type":"uint256[2]"},{"internalType":"uint256[4]","name":"g2pk","type":"uint256[4]"},{"internalType":"uint256","name":"votingPower","type":"uint256"}],"internalType":"struct IEOFeedVerifier.Validator[]","name":"newValidatorSet","type":"tuple[]"}],"name":"setNewValidatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"leafIndex","type":"uint256"},{"internalType":"bytes","name":"unhashedLeaf","type":"bytes"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"internalType":"struct IEOFeedVerifier.LeafInput","name":"input","type":"tuple"},{"components":[{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint32","name":"chainId","type":"uint32"},{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"bytes32","name":"eventRoot","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"uint256[2]","name":"signature","type":"uint256[2]"},{"internalType":"uint256[4]","name":"apkG2","type":"uint256[4]"},{"internalType":"bytes","name":"nonSignersBitmap","type":"bytes"}],"internalType":"struct IEOFeedVerifier.VerificationParams","name":"vParams","type":"tuple"}],"name":"verify","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052348015600f57600080fd5b506016601a565b60ca565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560695760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c75780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6122a6806100d96000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063cbc3882d11610081578063d1d5647011610066578063d1d56470146102f1578063f2fde38b14610304578063f896f1a51461031757600080fd5b8063cbc3882d146102be578063d15a9e38146102de57600080fd5b806394d76fa0116100b257806394d76fa01461026f57806395b0b0271461028d578063c9f8e264146102ab57600080fd5b8063715018a6146102095780638da5cb5b1461021157600080fd5b8063485cc955116101245780635ed1f963116101095780635ed1f963146101d9578063671b3793146101e15780636969a25c146101e957600080fd5b8063485cc9551461019d57806352a9674b146101b257600080fd5b80630d57a25d146101565780631d1d4f261461016d5780633faba508146101755780634578013b14610195575b600080fd5b6005545b6040519081526020015b60405180910390f35b60015461015a565b61018861018336600461196d565b61031f565b6040516101649190611a68565b60065461015a565b6101b06101ab366004611b0c565b610395565b005b61015a7f091ad028b53f66f6a3b10418ae9557a6bb44457040f02cc875d1c952547e3e2e81565b61015a600381565b60025461015a565b6101fc6101f7366004611b45565b6105c5565b6040516101649190611b5e565b6101b06106bd565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b60075473ffffffffffffffffffffffffffffffffffffffff1661024a565b60005473ffffffffffffffffffffffffffffffffffffffff1661024a565b6101b06102b9366004611be8565b6106d1565b6102d16102cc366004611c05565b61078f565b6040516101649190611c71565b6101b06102ec366004611be8565b610806565b6101b06102ff366004611c84565b6108d4565b6101b0610312366004611be8565b610c6c565b60045461015a565b60075460609073ffffffffffffffffffffffffffffffffffffffff163314610373576040517fdc55fa8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61037c82610cd5565b61038b84848460600135610e47565b90505b9392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156103e05750825b905060008267ffffffffffffffff1660011480156103fd5750303b155b90508115801561040b575080155b15610442576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156104a35784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b73ffffffffffffffffffffffffffffffffffffffff861615806104db575073ffffffffffffffffffffffffffffffffffffffff86163b155b15610512576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff881617905561055b87610f3d565b83156105bc5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105cd61187b565b6001548210610608576040517f99e56ef700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600360209081526040918290208251608081018452815473ffffffffffffffffffffffffffffffffffffffff16815283518085019485905290939192840191600184019060029082845b81548152602001906001019080831161065757505050918352505060408051608081019182905260209092019190600384019060049082845b81548152602001906001019080831161069057505050505081526020016007820154815250509050919050565b6106c5610f4e565b6106cf6000610fdc565b565b6106d9610f4e565b73ffffffffffffffffffffffffffffffffffffffff81161580610711575073ffffffffffffffffffffffffffffffffffffffff81163b155b15610748576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075460609073ffffffffffffffffffffffffffffffffffffffff1633146107e3576040517fdc55fa8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107ec82610cd5565b60006107fc848460600135611072565b9150505b92915050565b61080e610f4e565b73ffffffffffffffffffffffffffffffffffffffff811661085b576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fdfcb19105dbcc099629c92adee2128e656e2cd9922c3fb5fff61d5d925cc1a839060200160405180910390a150565b6108dc610f4e565b806003811015610918576040517f968c5cd500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228383611169565b610958576040517f9699f4a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001548110156109e157805b6001548110156109df57600081815260036020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681556001810182905560028101829055906000600383018190556004830181905560058301819055600683015550600060079190910155600101610964565b505b60018190556040516109f99084908490602001611cf9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600455828201909152600080835290820181905290815b83811015610c0a576000868683818110610a6257610a62611d78565b610a79926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff1603610ac6576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868683818110610ada57610ada611d78565b9050610100020160e00135905080600003610b21576040517f09559b0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b8185611dd6565b9350868683818110610b3f57610b3f611d78565b90506101000201600360008481526020019081526020016000208181610b659190611e2f565b505060005473ffffffffffffffffffffffffffffffffffffffff1663e9d1c41f84898986818110610b9857610b98611d78565b905061010002016020016040518363ffffffff1660e01b8152600401610bbf929190611f02565b6040805180830381865afa158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190611f1f565b925050600101610a46565b50610c1860088260026118c5565b50600282905560015460045460408051928352602083019190915281018390527f32febe8f400b26f85bcb935221e95020c9ccb6c17a8d7408b6053b913388a59b9060600160405180910390a15050505050565b610c74610f4e565b73ffffffffffffffffffffffffffffffffffffffff8116610cc9576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b610cd281610fdc565b50565b600654816060013503610ce55750565b60006060820135610cf96020840184611fc6565b6080840135610d0e6040860160208701611ff0565b610d1e6060870160408801611be8565b60408051602081019690965267ffffffffffffffff90941693850193909352606084019190915263ffffffff16608083015273ffffffffffffffffffffffffffffffffffffffff1660a082015260c001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090506060820135610de1576040517fb612e81c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e008160a0840160e08501610dfb610160870187612016565b611236565b600554610e106020840184611fc6565b67ffffffffffffffff161115610e4357610e2d6020830183611fc6565b67ffffffffffffffff1660055560608201356006555b5050565b60606000839003610e84576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260008167ffffffffffffffff811115610ea057610ea0611de9565b604051908082528060200260200182016040528015610ed357816020015b6060815260200190600190039081610ebe5790505b50905060005b82811015610f3357610f0e878783818110610ef657610ef6611d78565b9050602002810190610f089190612082565b86611072565b828281518110610f2057610f20611d78565b6020908102919091010152600101610ed9565b5095945050505050565b610f4561171e565b610cd281611785565b33610f8d7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146106cf576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610cc0565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b606060006110836020850185612016565b6040516110919291906120c0565b604051809103902090506110e98480604001906110ae91906120d0565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525087925085915061178d9050565b61111f576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112c6020850185612016565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092979650505050505050565b6000805b8281101561122c576000611182826001611dd6565b90505b838110156112235784848281811061119f5761119f611d78565b6111b6926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff168585848181106111de576111de611d78565b6111f5926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff160361121b57600092505050610800565b600101611185565b5060010161116d565b5060019392505050565b60408051808201909152600080825260208201819052600254905b6001548110156113d55760008181526003602090815260408083208151608081018352815473ffffffffffffffffffffffffffffffffffffffff1681528251808401938490529093919291840191600184019060029082845b8154815260200190600101908083116112aa57505050918352505060408051608081019182905260209092019190600384019060049082845b8154815260200190600101908083116112e3575050505050815260200160078201548152505090506113168686846117a3565b156113cc5760005460208201516040517fe9d1c41f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163e9d1c41f9161137791889190600401612138565b6040805180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b79190611f1f565b93508060600151836113c99190612153565b92505b50600101611251565b50600360025460026113e79190611e18565b6113f19190612195565b8111611429576040517fcabeb65500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000546040517f73d6746e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9d1c41f9060089083906373d6746e9061148a9088906004016121a9565b6040805180830381865afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca9190611f1f565b6040518363ffffffff1660e01b81526004016114e79291906121b7565b6040805180830381865afa158015611503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115279190611f1f565b600080546040805160208082018d905282518083039091018152818301928390527fa850a90900000000000000000000000000000000000000000000000000000000909252939550919273ffffffffffffffffffffffffffffffffffffffff9091169163a850a909916115be917f091ad028b53f66f6a3b10418ae9557a6bb44457040f02cc875d1c952547e3e2e916044016121ef565b6040805180830381865afa1580156115da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fe9190611f1f565b600080546040517f6822ce160000000000000000000000000000000000000000000000000000000081529293509091829173ffffffffffffffffffffffffffffffffffffffff1690636822ce16906116609088908d9088908e90600401612208565b6040805180830381865afa15801561167c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a09190612252565b91509150816116db576040517fe1062f6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80611712576040517f729d0f6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166106cf576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c7461171e565b60008261179a858461180c565b14949350505050565b6000806117b1600884612195565b905060006117c0600885612285565b90508482106117d45760009250505061038e565b6000600160ff83161b8787858181106117ef576117ef611d78565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b600081815b84518110156118475761183d8286838151811061183057611830611d78565b602002602001015161184f565b9150600101611811565b509392505050565b600081831061186b57600082815260208490526040902061038e565b5060009182526020526040902090565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016118ab611903565b81526020016118b8611921565b8152602001600081525090565b82600281019282156118f3579160200282015b828111156118f35782518255916020019190600101906118d8565b506118ff92915061193f565b5090565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b5b808211156118ff5760008155600101611940565b6000610180828403121561196757600080fd5b50919050565b60008060006040848603121561198257600080fd5b833567ffffffffffffffff8082111561199a57600080fd5b818601915086601f8301126119ae57600080fd5b8135818111156119bd57600080fd5b8760208260051b85010111156119d257600080fd5b6020928301955093509085013590808211156119ed57600080fd5b506119fa86828701611954565b9150509250925092565b6000815180845260005b81811015611a2a57602081850181015186830182015201611a0e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015611add577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452611acb858351611a04565b94509285019290850190600101611a91565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cd257600080fd5b60008060408385031215611b1f57600080fd5b8235611b2a81611aea565b91506020830135611b3a81611aea565b809150509250929050565b600060208284031215611b5757600080fd5b5035919050565b815173ffffffffffffffffffffffffffffffffffffffff1681526020808301516101008301919081840160005b6002811015611ba857825182529183019190830190600101611b8b565b50505060408401516060840160005b6004811015611bd457825182529183019190830190600101611bb7565b50505050606083015160e083015292915050565b600060208284031215611bfa57600080fd5b813561038e81611aea565b60008060408385031215611c1857600080fd5b823567ffffffffffffffff80821115611c3057600080fd5b9084019060608287031215611c4457600080fd5b90925060208401359080821115611c5a57600080fd5b50611c6785828601611954565b9150509250929050565b60208152600061038e6020830184611a04565b60008060208385031215611c9757600080fd5b823567ffffffffffffffff80821115611caf57600080fd5b818501915085601f830112611cc357600080fd5b813581811115611cd257600080fd5b8660208260081b8501011115611ce757600080fd5b60209290920196919550909350505050565b6020808252818101839052600090604080840186845b87811015611d6b578135611d2281611aea565b73ffffffffffffffffffffffffffffffffffffffff168352838286018685013760606080818401828601375060e082810135908401526101009283019290910190600101611d0f565b5090979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561080057610800611da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808202811582820484141761080057610800611da7565b8135611e3a81611aea565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825550602080830160005b6002811015611ea157813560018286018101919091559183019101611e81565b50506060830160005b6004811015611ec85781358482016003015590820190600101611eaa565b50505060e082013560078201555050565b8060005b6002811015611efc578151845260209384019390910190600101611edd565b50505050565b60808101611f108285611ed9565b60408360408401379392505050565b600060408284031215611f3157600080fd5b82601f830112611f4057600080fd5b6040516040810181811067ffffffffffffffff82111715611f8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250806040840185811115611fa157600080fd5b845b81811015611fbb578051835260209283019201611fa3565b509195945050505050565b600060208284031215611fd857600080fd5b813567ffffffffffffffff8116811461038e57600080fd5b60006020828403121561200257600080fd5b813563ffffffff8116811461038e57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261204b57600080fd5b83018035915067ffffffffffffffff82111561206657600080fd5b60200191503681900382131561207b57600080fd5b9250929050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126120b657600080fd5b9190910192915050565b8183823760009101908152919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261210557600080fd5b83018035915067ffffffffffffffff82111561212057600080fd5b6020019150600581901b360382131561207b57600080fd5b608081016121468285611ed9565b61038e6040830184611ed9565b8181038181111561080057610800611da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826121a4576121a4612166565b500490565b604081016108008284611ed9565b60808101818460005b60028110156121df5781548352602090920191600191820191016121c0565b50505061038e6040830184611ed9565b82815260406020820152600061038b6040830184611a04565b61014081016122178287611ed9565b604085604084013761222c6080830185611ed9565b60808360c084013795945050505050565b8051801515811461224d57600080fd5b919050565b6000806040838503121561226557600080fd5b61226e8361223d565b915061227c6020840161223d565b90509250929050565b60008261229457612294612166565b50069056fea164736f6c6343000819000a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063cbc3882d11610081578063d1d5647011610066578063d1d56470146102f1578063f2fde38b14610304578063f896f1a51461031757600080fd5b8063cbc3882d146102be578063d15a9e38146102de57600080fd5b806394d76fa0116100b257806394d76fa01461026f57806395b0b0271461028d578063c9f8e264146102ab57600080fd5b8063715018a6146102095780638da5cb5b1461021157600080fd5b8063485cc955116101245780635ed1f963116101095780635ed1f963146101d9578063671b3793146101e15780636969a25c146101e957600080fd5b8063485cc9551461019d57806352a9674b146101b257600080fd5b80630d57a25d146101565780631d1d4f261461016d5780633faba508146101755780634578013b14610195575b600080fd5b6005545b6040519081526020015b60405180910390f35b60015461015a565b61018861018336600461196d565b61031f565b6040516101649190611a68565b60065461015a565b6101b06101ab366004611b0c565b610395565b005b61015a7f091ad028b53f66f6a3b10418ae9557a6bb44457040f02cc875d1c952547e3e2e81565b61015a600381565b60025461015a565b6101fc6101f7366004611b45565b6105c5565b6040516101649190611b5e565b6101b06106bd565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b60075473ffffffffffffffffffffffffffffffffffffffff1661024a565b60005473ffffffffffffffffffffffffffffffffffffffff1661024a565b6101b06102b9366004611be8565b6106d1565b6102d16102cc366004611c05565b61078f565b6040516101649190611c71565b6101b06102ec366004611be8565b610806565b6101b06102ff366004611c84565b6108d4565b6101b0610312366004611be8565b610c6c565b60045461015a565b60075460609073ffffffffffffffffffffffffffffffffffffffff163314610373576040517fdc55fa8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61037c82610cd5565b61038b84848460600135610e47565b90505b9392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156103e05750825b905060008267ffffffffffffffff1660011480156103fd5750303b155b90508115801561040b575080155b15610442576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156104a35784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b73ffffffffffffffffffffffffffffffffffffffff861615806104db575073ffffffffffffffffffffffffffffffffffffffff86163b155b15610512576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff881617905561055b87610f3d565b83156105bc5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6105cd61187b565b6001548210610608576040517f99e56ef700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600360209081526040918290208251608081018452815473ffffffffffffffffffffffffffffffffffffffff16815283518085019485905290939192840191600184019060029082845b81548152602001906001019080831161065757505050918352505060408051608081019182905260209092019190600384019060049082845b81548152602001906001019080831161069057505050505081526020016007820154815250509050919050565b6106c5610f4e565b6106cf6000610fdc565b565b6106d9610f4e565b73ffffffffffffffffffffffffffffffffffffffff81161580610711575073ffffffffffffffffffffffffffffffffffffffff81163b155b15610748576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075460609073ffffffffffffffffffffffffffffffffffffffff1633146107e3576040517fdc55fa8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107ec82610cd5565b60006107fc848460600135611072565b9150505b92915050565b61080e610f4e565b73ffffffffffffffffffffffffffffffffffffffff811661085b576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fdfcb19105dbcc099629c92adee2128e656e2cd9922c3fb5fff61d5d925cc1a839060200160405180910390a150565b6108dc610f4e565b806003811015610918576040517f968c5cd500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228383611169565b610958576040517f9699f4a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001548110156109e157805b6001548110156109df57600081815260036020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681556001810182905560028101829055906000600383018190556004830181905560058301819055600683015550600060079190910155600101610964565b505b60018190556040516109f99084908490602001611cf9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600455828201909152600080835290820181905290815b83811015610c0a576000868683818110610a6257610a62611d78565b610a79926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff1603610ac6576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868683818110610ada57610ada611d78565b9050610100020160e00135905080600003610b21576040517f09559b0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b8185611dd6565b9350868683818110610b3f57610b3f611d78565b90506101000201600360008481526020019081526020016000208181610b659190611e2f565b505060005473ffffffffffffffffffffffffffffffffffffffff1663e9d1c41f84898986818110610b9857610b98611d78565b905061010002016020016040518363ffffffff1660e01b8152600401610bbf929190611f02565b6040805180830381865afa158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190611f1f565b925050600101610a46565b50610c1860088260026118c5565b50600282905560015460045460408051928352602083019190915281018390527f32febe8f400b26f85bcb935221e95020c9ccb6c17a8d7408b6053b913388a59b9060600160405180910390a15050505050565b610c74610f4e565b73ffffffffffffffffffffffffffffffffffffffff8116610cc9576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b610cd281610fdc565b50565b600654816060013503610ce55750565b60006060820135610cf96020840184611fc6565b6080840135610d0e6040860160208701611ff0565b610d1e6060870160408801611be8565b60408051602081019690965267ffffffffffffffff90941693850193909352606084019190915263ffffffff16608083015273ffffffffffffffffffffffffffffffffffffffff1660a082015260c001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090506060820135610de1576040517fb612e81c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e008160a0840160e08501610dfb610160870187612016565b611236565b600554610e106020840184611fc6565b67ffffffffffffffff161115610e4357610e2d6020830183611fc6565b67ffffffffffffffff1660055560608201356006555b5050565b60606000839003610e84576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260008167ffffffffffffffff811115610ea057610ea0611de9565b604051908082528060200260200182016040528015610ed357816020015b6060815260200190600190039081610ebe5790505b50905060005b82811015610f3357610f0e878783818110610ef657610ef6611d78565b9050602002810190610f089190612082565b86611072565b828281518110610f2057610f20611d78565b6020908102919091010152600101610ed9565b5095945050505050565b610f4561171e565b610cd281611785565b33610f8d7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146106cf576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610cc0565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b606060006110836020850185612016565b6040516110919291906120c0565b604051809103902090506110e98480604001906110ae91906120d0565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525087925085915061178d9050565b61111f576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112c6020850185612016565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092979650505050505050565b6000805b8281101561122c576000611182826001611dd6565b90505b838110156112235784848281811061119f5761119f611d78565b6111b6926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff168585848181106111de576111de611d78565b6111f5926020610100909202019081019150611be8565b73ffffffffffffffffffffffffffffffffffffffff160361121b57600092505050610800565b600101611185565b5060010161116d565b5060019392505050565b60408051808201909152600080825260208201819052600254905b6001548110156113d55760008181526003602090815260408083208151608081018352815473ffffffffffffffffffffffffffffffffffffffff1681528251808401938490529093919291840191600184019060029082845b8154815260200190600101908083116112aa57505050918352505060408051608081019182905260209092019190600384019060049082845b8154815260200190600101908083116112e3575050505050815260200160078201548152505090506113168686846117a3565b156113cc5760005460208201516040517fe9d1c41f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163e9d1c41f9161137791889190600401612138565b6040805180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b79190611f1f565b93508060600151836113c99190612153565b92505b50600101611251565b50600360025460026113e79190611e18565b6113f19190612195565b8111611429576040517fcabeb65500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000546040517f73d6746e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9d1c41f9060089083906373d6746e9061148a9088906004016121a9565b6040805180830381865afa1580156114a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ca9190611f1f565b6040518363ffffffff1660e01b81526004016114e79291906121b7565b6040805180830381865afa158015611503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115279190611f1f565b600080546040805160208082018d905282518083039091018152818301928390527fa850a90900000000000000000000000000000000000000000000000000000000909252939550919273ffffffffffffffffffffffffffffffffffffffff9091169163a850a909916115be917f091ad028b53f66f6a3b10418ae9557a6bb44457040f02cc875d1c952547e3e2e916044016121ef565b6040805180830381865afa1580156115da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fe9190611f1f565b600080546040517f6822ce160000000000000000000000000000000000000000000000000000000081529293509091829173ffffffffffffffffffffffffffffffffffffffff1690636822ce16906116609088908d9088908e90600401612208565b6040805180830381865afa15801561167c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a09190612252565b91509150816116db576040517fe1062f6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80611712576040517f729d0f6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166106cf576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c7461171e565b60008261179a858461180c565b14949350505050565b6000806117b1600884612195565b905060006117c0600885612285565b90508482106117d45760009250505061038e565b6000600160ff83161b8787858181106117ef576117ef611d78565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b600081815b84518110156118475761183d8286838151811061183057611830611d78565b602002602001015161184f565b9150600101611811565b509392505050565b600081831061186b57600082815260208490526040902061038e565b5060009182526020526040902090565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016118ab611903565b81526020016118b8611921565b8152602001600081525090565b82600281019282156118f3579160200282015b828111156118f35782518255916020019190600101906118d8565b506118ff92915061193f565b5090565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b5b808211156118ff5760008155600101611940565b6000610180828403121561196757600080fd5b50919050565b60008060006040848603121561198257600080fd5b833567ffffffffffffffff8082111561199a57600080fd5b818601915086601f8301126119ae57600080fd5b8135818111156119bd57600080fd5b8760208260051b85010111156119d257600080fd5b6020928301955093509085013590808211156119ed57600080fd5b506119fa86828701611954565b9150509250925092565b6000815180845260005b81811015611a2a57602081850181015186830182015201611a0e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015611add577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452611acb858351611a04565b94509285019290850190600101611a91565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cd257600080fd5b60008060408385031215611b1f57600080fd5b8235611b2a81611aea565b91506020830135611b3a81611aea565b809150509250929050565b600060208284031215611b5757600080fd5b5035919050565b815173ffffffffffffffffffffffffffffffffffffffff1681526020808301516101008301919081840160005b6002811015611ba857825182529183019190830190600101611b8b565b50505060408401516060840160005b6004811015611bd457825182529183019190830190600101611bb7565b50505050606083015160e083015292915050565b600060208284031215611bfa57600080fd5b813561038e81611aea565b60008060408385031215611c1857600080fd5b823567ffffffffffffffff80821115611c3057600080fd5b9084019060608287031215611c4457600080fd5b90925060208401359080821115611c5a57600080fd5b50611c6785828601611954565b9150509250929050565b60208152600061038e6020830184611a04565b60008060208385031215611c9757600080fd5b823567ffffffffffffffff80821115611caf57600080fd5b818501915085601f830112611cc357600080fd5b813581811115611cd257600080fd5b8660208260081b8501011115611ce757600080fd5b60209290920196919550909350505050565b6020808252818101839052600090604080840186845b87811015611d6b578135611d2281611aea565b73ffffffffffffffffffffffffffffffffffffffff168352838286018685013760606080818401828601375060e082810135908401526101009283019290910190600101611d0f565b5090979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561080057610800611da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808202811582820484141761080057610800611da7565b8135611e3a81611aea565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825550602080830160005b6002811015611ea157813560018286018101919091559183019101611e81565b50506060830160005b6004811015611ec85781358482016003015590820190600101611eaa565b50505060e082013560078201555050565b8060005b6002811015611efc578151845260209384019390910190600101611edd565b50505050565b60808101611f108285611ed9565b60408360408401379392505050565b600060408284031215611f3157600080fd5b82601f830112611f4057600080fd5b6040516040810181811067ffffffffffffffff82111715611f8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250806040840185811115611fa157600080fd5b845b81811015611fbb578051835260209283019201611fa3565b509195945050505050565b600060208284031215611fd857600080fd5b813567ffffffffffffffff8116811461038e57600080fd5b60006020828403121561200257600080fd5b813563ffffffff8116811461038e57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261204b57600080fd5b83018035915067ffffffffffffffff82111561206657600080fd5b60200191503681900382131561207b57600080fd5b9250929050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126120b657600080fd5b9190910192915050565b8183823760009101908152919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261210557600080fd5b83018035915067ffffffffffffffff82111561212057600080fd5b6020019150600581901b360382131561207b57600080fd5b608081016121468285611ed9565b61038e6040830184611ed9565b8181038181111561080057610800611da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826121a4576121a4612166565b500490565b604081016108008284611ed9565b60808101818460005b60028110156121df5781548352602090920191600191820191016121c0565b50505061038e6040830184611ed9565b82815260406020820152600061038b6040830184611a04565b61014081016122178287611ed9565b604085604084013761222c6080830185611ed9565b60808360c084013795945050505050565b8051801515811461224d57600080fd5b919050565b6000806040838503121561226557600080fd5b61226e8361223d565b915061227c6020840161223d565b90509250929050565b60008261229457612294612166565b50069056fea164736f6c6343000819000a
Deployed Bytecode Sourcemap
1174:12422:4:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7283:117;7368:25;;7283:117;;;160:25:8;;;148:2;133:18;7283:117:4;;;;;;;;6085:119;6171:26;;6085:119;;3451:283;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;7535:113::-;7618:23;;7535:113;;2727:250;;;;;;:::i;:::-;;:::i;:::-;;1243:67;;1276:34;1243:67;;1316:42;;1357:1;1316:42;;6341:101;6418:17;;6341:101;;6670:221;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;3155:101:0:-;;;:::i;2441:144::-;1313:22;2570:8;;;2441:144;;;4828:42:8;4816:55;;;4798:74;;4786:2;4771:18;2441:144:0;4652:226:8;7774:91:4;7846:12;;;;7774:91;;7871:72;7909:4;7932;;;7871:72;;5741:198;;;;;;:::i;:::-;;:::i;3090:304::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;5419:217::-;;;;;;:::i;:::-;;:::i;3868:1412::-;;;;;;:::i;:::-;;:::i;3405:215:0:-;;;;;;:::i;:::-;;:::i;7029:115:4:-;7113:24;;7029:115;;3451:283;2390:12;;3618:14;;2390:12;;2376:10;:26;2372:63;;2411:24;;;;;;;;;;;;;;2372:63;3648:22:::1;3662:7;3648:13;:22::i;:::-;3687:40;3701:6;;3709:7;:17;;;3687:13;:40::i;:::-;3680:47;;2445:1;3451:283:::0;;;;;:::o;2727:250::-;8870:21:1;4302:15;;;;;;;4301:16;;4348:14;;4158:30;4726:16;;:34;;;;;4746:14;4726:34;4706:54;;4770:17;4790:11;:16;;4805:1;4790:16;:50;;;;-1:-1:-1;4818:4:1;4810:25;:30;4790:50;4770:70;;4856:12;4855:13;:30;;;;;4873:12;4872:13;4855:30;4851:91;;;4908:23;;;;;;;;;;;;;;4851:91;4951:18;;;;4968:1;4951:18;;;4979:67;;;;5013:22;;;;;;;;4979:67;2808:27:4::1;::::0;::::1;::::0;;:61:::1;;-1:-1:-1::0;2839:25:4::1;::::0;::::1;;:30:::0;2808:61:::1;2804:115;;;2892:16;;;;;;;;;;;;;;2804:115;2928:4;:11:::0;;;::::1;;::::0;::::1;;::::0;;2949:21:::1;2964:5:::0;2949:14:::1;:21::i;:::-;5070:14:1::0;5066:101;;;5100:23;;;;;;5142:14;;-1:-1:-1;7338:50:8;;5142:14:1;;7326:2:8;7311:18;5142:14:1;;;;;;;5066:101;4092:1081;;;;;2727:250:4;;:::o;6670:221::-;6737:16;;:::i;:::-;6778:26;;6769:5;:35;6765:75;;6813:27;;;;;;;;;;;;;;6765:75;6857:27;;;;:20;:27;;;;;;;;;6850:34;;;;;;;;;;;;;;;;;;;;;;;;6857:27;;6850:34;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6850:34:4;;;-1:-1:-1;;6850:34:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6670:221;;;:::o;3155:101:0:-;2334:13;:11;:13::i;:::-;3219:30:::1;3246:1;3219:18;:30::i;:::-;3155:101::o:0;5741:198:4:-;2334:13:0;:11;:13::i;:::-;5801:27:4::1;::::0;::::1;::::0;;:61:::1;;-1:-1:-1::0;5832:25:4::1;::::0;::::1;;:30:::0;5801:61:::1;5797:115;;;5885:16;;;;;;;;;;;;;;5797:115;5921:4;:11:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;5741:198::o;3090:304::-;2390:12;;3249;;2390;;2376:10;:26;2372:63;;2411:24;;;;;;;;;;;;;;2372:63;3277:22:::1;3291:7;3277:13;:22::i;:::-;3309:17;3329:37;3341:5;3348:7;:17;;;3329:11;:37::i;:::-;3309:57:::0;-1:-1:-1;;2445:1:4::1;3090:304:::0;;;;:::o;5419:217::-;2334:13:0;:11;:13::i;:::-;5498:26:4::1;::::0;::::1;5494:55;;5533:16;;;;;;;;;;;;;;5494:55;5559:12;:27:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;5601:28:::1;::::0;4798:74:8;;;5601:28:4::1;::::0;4786:2:8;4771:18;5601:28:4::1;;;;;;;5419:217:::0;:::o;3868:1412::-;2334:13:0;:11;:13::i;:::-;3980:15:4;1357:1:::1;4016:23:::0;::::1;4012:58;;;4048:22;;;;;;;;;;;;;;4012:58;4085:40;4109:15;;4085:23;:40::i;:::-;4080:75;;4134:21;;;;;;;;;;;;;;4080:75;4178:26;;4169:6;:35;4165:247;;;4237:6:::0;4220:182:::1;4249:26;;4245:1;:30;4220:182;;;4364:23;::::0;;;:20:::1;:23;::::0;;;;4357:30;;;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;;;;;4364:23:4;4357:30:::1;;::::0;::::1;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;4357:30:4::1;;::::0;;;::::1;::::0;4277:3:::1;;4220:182;;;;4165:247;4422:26;:35:::0;;;4504:27:::1;::::0;::::1;::::0;4515:15;;;;4504:27:::1;;;:::i;:::-;;::::0;;;;;::::1;::::0;;;;;;4494:38;;4504:27:::1;4494:38:::0;;::::1;::::0;4467:24:::1;:65:::0;4574:48;;::::1;::::0;;;4542:18:::1;4574:48:::0;;;;;::::1;::::0;;;4542:18;;4633:469:::1;4657:6;4653:1;:10;4633:469;;;4727:1;4688:15:::0;;4704:1;4688:18;;::::1;;;;;:::i;:::-;:27;::::0;::::1;:18;::::0;;::::1;;:27:::0;;::::1;::::0;-1:-1:-1;4688:27:4::1;:::i;:::-;:41;;::::0;4684:70:::1;;4738:16;;;;;;;;;;;;;;4684:70;4768:19;4790:15;;4806:1;4790:18;;;;;;;:::i;:::-;;;;;;:30;;;4768:52;;4838:11;4853:1;4838:16:::0;4834:48:::1;;4863:19;;;;;;;;;;;;;;4834:48;4896:25;4910:11:::0;4896:25;::::1;:::i;:::-;;;4961:15;;4977:1;4961:18;;;;;;;:::i;:::-;;;;;;4935:20;:23;4956:1;4935:23;;;;;;;;;;;:44;;;;;;:::i;:::-;-1:-1:-1::0;;5051:4:4::1;::::0;::::1;;:10;5062:3:::0;5067:15;;5083:1;5067:18;;::::1;;;;;:::i;:::-;;;;;;:23;;5051:40;;;;;;;;;;;;;;;;:::i;:::-;;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5045:46:::0;-1:-1:-1;;4665:3:4::1;;4633:469;;;-1:-1:-1::0;5112:14:4::1;:8;5123:3:::0;5112:14:::1;;:::i;:::-;-1:-1:-1::0;5136:17:4::1;:30:::0;;;5201:26:::1;::::0;5229:24:::1;::::0;5181:92:::1;::::0;;12172:25:8;;;12228:2;12213:18;;12206:34;;;;12256:18;;12249:34;;;5181:92:4::1;::::0;12160:2:8;12145:18;5181:92:4::1;;;;;;;3953:1327;;;3868:1412:::0;;:::o;3405:215:0:-;2334:13;:11;:13::i;:::-;3489:22:::1;::::0;::::1;3485:91;;3534:31;::::0;::::1;::::0;;3562:1:::1;3534:31;::::0;::::1;4798:74:8::0;4771:18;;3534:31:0::1;;;;;;;;3485:91;3585:28;3604:8;3585:18;:28::i;:::-;3405:215:::0;:::o;8114:807:4:-;8330:23;;8309:7;:17;;;:44;8305:81;;8114:807;:::o;8305:81::-;8396:15;8448:17;;;;8467:19;;;;8448:7;8467:19;:::i;:::-;8488:17;;;;8507:15;;;;;;;;:::i;:::-;8524:18;;;;;;;;:::i;:::-;8437:106;;;;;;13119:25:8;;;;13192:18;13180:31;;;13160:18;;;13153:59;;;;13228:18;;;13221:34;;;;13303:10;13291:23;13271:18;;;13264:51;13364:42;13352:55;13331:19;;;13324:84;13091:19;;8437:106:4;;;;;;;;;;;;;8414:139;;8437:106;8414:139;;;;;-1:-1:-1;8568:17:4;;;;8564:62;;8608:18;;;;;;;;;;;;;;8564:62;8637:85;8654:7;8663:17;;;8682:13;;;8697:24;;;;8663:7;8697:24;:::i;:::-;8637:16;:85::i;:::-;8759:25;;8737:19;;;;:7;:19;:::i;:::-;:47;;;8733:182;;;8828:19;;;;:7;:19;:::i;:::-;8800:47;;:25;:47;8887:17;;;;8861:23;:43;8733:182;8199:722;8114:807;:::o;10821:416::-;10915:14;10962:1;10945:18;;;10941:45;;10972:14;;;;;;;;;;;;;;10941:45;11013:6;10996:14;11013:6;11064:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11036:47;;11098:9;11093:111;11117:6;11113:1;:10;11093:111;;;11160:33;11172:6;;11179:1;11172:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;11183;11160:11;:33::i;:::-;11144:10;11155:1;11144:13;;;;;;;;:::i;:::-;;;;;;;;;;:49;11125:3;;11093:111;;;-1:-1:-1;11220:10:4;10821:416;-1:-1:-1;;;;;10821:416:4:o;1847:127:0:-;6931:20:1;:18;:20::i;:::-;1929:38:0::1;1954:12;1929:24;:38::i;2658:162::-:0;966:10:2;2717:7:0;1313:22;2570:8;;;;2441:144;2717:7;:23;;;2713:101;;2763:40;;;;;966:10:2;2763:40:0;;;4798:74:8;4771:18;;2763:40:0;4652:226:8;3774:248:0;1313:22;3923:8;;3941:19;;;3923:8;3941:19;;;;;;;;3975:40;;3923:8;;;;;3975:40;;3847:24;;3975:40;3837:185;;3774:248;:::o;11425:311:4:-;11514:12;11538;11563:18;;;;:5;:18;:::i;:::-;11553:29;;;;;;;:::i;:::-;;;;;;;;11538:44;;11598:48;11617:5;:11;;;;;;;;:::i;:::-;11598:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11630:9:4;;-1:-1:-1;11641:4:4;;-1:-1:-1;11598:18:4;;-1:-1:-1;11598:48:4:i;:::-;11593:101;;11669:14;;;;;;;;;;;;;;11593:101;11711:18;;;;:5;:18;:::i;:::-;11704:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11704:25:4;;11425:311;-1:-1:-1;;;;;;;11425:311:4:o;12876:394::-;12964:4;;12980:263;13000:21;;;12980:263;;;13047:9;13059:5;:1;13063;13059:5;:::i;:::-;13047:17;;13042:191;13066:21;;;13042:191;;;13142:10;;13153:1;13142:13;;;;;;;:::i;:::-;:22;;;:13;;;;;:22;;;;-1:-1:-1;13142:22:4;:::i;:::-;13116:48;;:10;;13127:1;13116:13;;;;;;;:::i;:::-;:22;;;:13;;;;;:22;;;;-1:-1:-1;13116:22:4;:::i;:::-;:48;;;13112:107;;13195:5;13188:12;;;;;;13112:107;13089:3;;13042:191;;;-1:-1:-1;13023:3:4;;12980:263;;;-1:-1:-1;13259:4:4;;12876:394;-1:-1:-1;;;12876:394:4:o;9264:1319::-;9484:48;;;;;;;;;:21;:48;;;;;;;;;9567:17;;;9641:296;9665:26;;9661:1;:30;9641:296;;;9712:18;9733:23;;;:20;:23;;;;;;;;9712:44;;;;;;;;;;;;;;;;;;;;;;;;9733:23;;9712:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9712:44:4;;;-1:-1:-1;;9712:44:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9774:40;9794:16;;9812:1;9774:19;:40::i;:::-;9770:157;;;9840:4;;9856:6;;;;9840:23;;;;;:4;;;;;:10;;:23;;9851:3;;9856:6;9840:23;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9834:29;;9899:1;:13;;;9881:31;;;;;:::i;:::-;;;9770:157;-1:-1:-1;9693:3:4;;9641:296;;;;10058:1;10037:17;;10033:1;:21;;;;:::i;:::-;10032:27;;;;:::i;:::-;10013:14;:47;10009:85;;10069:25;;;;;;;;;;;;;;10009:85;10174:4;;10195:13;;;;;10174:4;;;;;:10;;10185:8;;10174:4;;10195:8;;:13;;10204:3;;10195:13;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10174:35;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10219:27;10249:4;;10274:29;;;;;;;17089:19:8;;;10274:29:4;;;;;;;;;;17124:12:8;;;10274:29:4;;;;10249:55;;;;10168:41;;-1:-1:-1;10219:27:4;;10249:4;;;;;:16;;:55;;1276:34;;10249:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10315:22;10376:4;;:65;;;;;10219:85;;-1:-1:-1;10315:22:4;;;;10376:4;;;:31;;:65;;10408:3;;10413:9;;10219:85;;10435:5;;10376:65;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10314:127;;;;10457:17;10452:55;;10483:24;;;;;;;;;;;;;;10452:55;10522:16;10517:59;;10547:29;;;;;;;;;;;;;;10517:59;9474:1109;;;;;9264:1319;;;;;:::o;7084:141:1:-;8870:21;8560:40;;;;;;7146:73;;7191:17;;;;;;;;;;;;;;1980:235:0;6931:20:1;:18;:20::i;1265:154:3:-;1356:4;1408;1379:25;1392:5;1399:4;1379:12;:25::i;:::-;:33;;1265:154;-1:-1:-1;;;;1265:154:3:o;12145:479:4:-;12234:4;;12271:9;12279:1;12271:5;:9;:::i;:::-;12250:30;-1:-1:-1;12362:15:4;12386:9;12394:1;12386:5;:9;:::i;:::-;12362:34;-1:-1:-1;12411:27:4;;;12407:70;;12461:5;12454:12;;;;;;12407:70;12616:1;12598;:14;;;;12575:6;;12582:10;12575:18;;;;;;;:::i;:::-;;;;;;;;;12569:25;;:44;;;:48;12562:55;;;;12145:479;;;;;:::o;1967:290:3:-;2050:7;2092:4;2050:7;2106:116;2130:5;:12;2126:1;:16;2106:116;;;2178:33;2188:12;2202:5;2208:1;2202:8;;;;;;;;:::i;:::-;;;;;;;2178:9;:33::i;:::-;2163:48;-1:-1:-1;2144:3:3;;2106:116;;;-1:-1:-1;2238:12:3;1967:290;-1:-1:-1;;;1967:290:3:o;9229:147::-;9292:7;9322:1;9318;:5;:51;;9564:13;9655:15;;;9690:4;9683:15;;;9736:4;9720:21;;9318:51;;;-1:-1:-1;9564:13:3;9655:15;;;9690:4;9683:15;9736:4;9720:21;;;9229:147::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;196:167:8;267:5;312:3;303:6;298:3;294:16;290:26;287:46;;;329:1;326;319:12;287:46;-1:-1:-1;351:6:8;196:167;-1:-1:-1;196:167:8:o;368:906::-;530:6;538;546;599:2;587:9;578:7;574:23;570:32;567:52;;;615:1;612;605:12;567:52;655:9;642:23;684:18;725:2;717:6;714:14;711:34;;;741:1;738;731:12;711:34;779:6;768:9;764:22;754:32;;824:7;817:4;813:2;809:13;805:27;795:55;;846:1;843;836:12;795:55;886:2;873:16;912:2;904:6;901:14;898:34;;;928:1;925;918:12;898:34;983:7;976:4;966:6;963:1;959:14;955:2;951:23;947:34;944:47;941:67;;;1004:1;1001;994:12;941:67;1035:4;1027:13;;;;-1:-1:-1;1059:6:8;-1:-1:-1;1103:20:8;;;1090:34;;1136:16;;;1133:36;;;1165:1;1162;1155:12;1133:36;;1188:80;1260:7;1249:8;1238:9;1234:24;1188:80;:::i;:::-;1178:90;;;368:906;;;;;:::o;1279:481::-;1320:3;1358:5;1352:12;1385:6;1380:3;1373:19;1410:1;1420:162;1434:6;1431:1;1428:13;1420:162;;;1496:4;1552:13;;;1548:22;;1542:29;1524:11;;;1520:20;;1513:59;1449:12;1420:162;;;1424:3;1627:1;1620:4;1611:6;1606:3;1602:16;1598:27;1591:38;1749:4;1679:66;1674:2;1666:6;1662:15;1658:88;1653:3;1649:98;1645:109;1638:116;;;1279:481;;;;:::o;1765:859::-;1925:4;1954:2;1994;1983:9;1979:18;2024:2;2013:9;2006:21;2047:6;2082;2076:13;2113:6;2105;2098:22;2151:2;2140:9;2136:18;2129:25;;2213:2;2203:6;2200:1;2196:14;2185:9;2181:30;2177:39;2163:53;;2251:2;2243:6;2239:15;2272:1;2282:313;2296:6;2293:1;2290:13;2282:313;;;2385:66;2373:9;2365:6;2361:22;2357:95;2352:3;2345:108;2476:39;2508:6;2499;2493:13;2476:39;:::i;:::-;2466:49;-1:-1:-1;2573:12:8;;;;2538:15;;;;2318:1;2311:9;2282:313;;;-1:-1:-1;2612:6:8;;1765:859;-1:-1:-1;;;;;;;1765:859:8:o;2811:154::-;2897:42;2890:5;2886:54;2879:5;2876:65;2866:93;;2955:1;2952;2945:12;2970:401;3051:6;3059;3112:2;3100:9;3091:7;3087:23;3083:32;3080:52;;;3128:1;3125;3118:12;3080:52;3167:9;3154:23;3186:31;3211:5;3186:31;:::i;:::-;3236:5;-1:-1:-1;3293:2:8;3278:18;;3265:32;3306:33;3265:32;3306:33;:::i;:::-;3358:7;3348:17;;;2970:401;;;;;:::o;3376:180::-;3435:6;3488:2;3476:9;3467:7;3463:23;3459:32;3456:52;;;3504:1;3501;3494:12;3456:52;-1:-1:-1;3527:23:8;;3376:180;-1:-1:-1;3376:180:8:o;3561:1086::-;3784:13;;3799:42;3780:62;3762:81;;3862:4;3901:15;;;3895:22;3749:3;3734:19;;;3862:4;3937:18;;;3707:4;4037:167;4051:4;4048:1;4045:11;4037:167;;;4110:13;;4098:26;;4179:15;;;;4144:12;;;;4071:1;4064:9;4037:167;;;4041:3;;;4253:4;4245:6;4241:17;4235:24;4296:4;4285:9;4281:20;4383:1;4393:185;4409:4;4404:3;4401:13;4393:185;;;4474:15;;4460:30;;4551:17;;;;4512:14;;;;4433:1;4424:11;4393:185;;;4397:3;;;;4634:4;4626:6;4622:17;4616:24;4609:4;4598:9;4594:20;4587:54;3561:1086;;;;:::o;5127:260::-;5199:6;5252:2;5240:9;5231:7;5227:23;5223:32;5220:52;;;5268:1;5265;5258:12;5220:52;5307:9;5294:23;5326:31;5351:5;5326:31;:::i;5392:665::-;5527:6;5535;5588:2;5576:9;5567:7;5563:23;5559:32;5556:52;;;5604:1;5601;5594:12;5556:52;5644:9;5631:23;5673:18;5714:2;5706:6;5703:14;5700:34;;;5730:1;5727;5720:12;5700:34;5753:22;;;;5809:2;5791:16;;;5787:25;5784:45;;;5825:1;5822;5815:12;5784:45;5848:2;;-1:-1:-1;5903:2:8;5888:18;;5875:32;;5919:16;;;5916:36;;;5948:1;5945;5938:12;5916:36;;5971:80;6043:7;6032:8;6021:9;6017:24;5971:80;:::i;:::-;5961:90;;;5392:665;;;;;:::o;6062:217::-;6209:2;6198:9;6191:21;6172:4;6229:44;6269:2;6258:9;6254:18;6246:6;6229:44;:::i;6536:644::-;6651:6;6659;6712:2;6700:9;6691:7;6687:23;6683:32;6680:52;;;6728:1;6725;6718:12;6680:52;6768:9;6755:23;6797:18;6838:2;6830:6;6827:14;6824:34;;;6854:1;6851;6844:12;6824:34;6892:6;6881:9;6877:22;6867:32;;6937:7;6930:4;6926:2;6922:13;6918:27;6908:55;;6959:1;6956;6949:12;6908:55;6999:2;6986:16;7025:2;7017:6;7014:14;7011:34;;;7041:1;7038;7031:12;7011:34;7094:7;7089:2;7079:6;7076:1;7072:14;7068:2;7064:23;7060:32;7057:45;7054:65;;;7115:1;7112;7105:12;7054:65;7146:2;7138:11;;;;;7168:6;;-1:-1:-1;6536:644:8;;-1:-1:-1;;;;6536:644:8:o;7399:1074::-;7636:2;7688:21;;;7661:18;;;7744:22;;;7607:4;;7785:2;7803:18;;;7844:6;7607:4;7878:569;7892:6;7889:1;7886:13;7878:569;;;7967:6;7954:20;7987:31;8012:5;7987:31;:::i;:::-;8054:42;8043:54;8031:67;;8155:2;8138:15;;;8124:12;;;8111:47;8181:4;8242;8237:2;8229:6;8225:15;8220:2;8215:3;8211:12;8198:49;-1:-1:-1;8270:4:8;8321:15;;;8308:29;8294:12;;;8287:51;8361:6;8387:12;;;;8422:15;;;;7914:1;7907:9;7878:569;;;-1:-1:-1;8464:3:8;;7399:1074;-1:-1:-1;;;;;;;7399:1074:8:o;8478:184::-;8530:77;8527:1;8520:88;8627:4;8624:1;8617:15;8651:4;8648:1;8641:15;8667:184;8719:77;8716:1;8709:88;8816:4;8813:1;8806:15;8840:4;8837:1;8830:15;8856:125;8921:9;;;8942:10;;;8939:36;;;8955:18;;:::i;8986:184::-;9038:77;9035:1;9028:88;9135:4;9132:1;9125:15;9159:4;9156:1;9149:15;9175:168;9248:9;;;9279;;9296:15;;;9290:22;;9276:37;9266:71;;9317:18;;:::i;9348:989::-;9517:5;9504:19;9532:33;9557:7;9532:33;:::i;:::-;9689:42;9680:7;9676:56;9607:66;9600:4;9594:11;9590:84;9587:146;9581:4;9574:160;;9753:2;9789;9782:5;9778:14;9810:1;9820:184;9834:4;9831:1;9828:11;9820:184;;;9891:20;;9987:1;9973:12;;;9969:20;;9962:32;;;;9934:15;;;;9847:9;9820:184;;;9824:3;;10040:2;10033:5;10029:14;10063:1;10073:198;10089:4;10084:3;10081:13;10073:198;;;10150:22;;10238:14;;;10254:1;10234:22;10227:34;10197:17;;;;10113:1;10104:11;10073:198;;;10077:3;;;10325;10318:5;10314:15;10301:29;10297:1;10291:4;10287:12;10280:51;9348:989;;:::o;10342:326::-;10435:5;10458:1;10468:194;10482:4;10479:1;10476:11;10468:194;;;10541:13;;10529:26;;10578:4;10602:12;;;;10637:15;;;;10502:1;10495:9;10468:194;;;10472:3;;10342:326;;:::o;10673:371::-;10929:3;10914:19;;10942:43;10918:9;10967:6;10942:43;:::i;:::-;11035:2;11027:6;11022:2;11011:9;11007:18;10994:44;10673:371;;;;;:::o;11049:916::-;11142:6;11195:2;11183:9;11174:7;11170:23;11166:32;11163:52;;;11211:1;11208;11201:12;11163:52;11260:7;11253:4;11242:9;11238:20;11234:34;11224:62;;11282:1;11279;11272:12;11224:62;11315:2;11309:9;11357:2;11349:6;11345:15;11426:6;11414:10;11411:22;11390:18;11378:10;11375:34;11372:62;11369:242;;;11467:77;11464:1;11457:88;11568:4;11565:1;11558:15;11596:4;11593:1;11586:15;11369:242;11631:10;11627:2;11620:22;;11662:6;11706:2;11695:9;11691:18;11732:7;11724:6;11721:19;11718:39;;;11753:1;11750;11743:12;11718:39;11777:9;11795:139;11811:6;11806:3;11803:15;11795:139;;;11879:10;;11867:23;;11919:4;11910:14;;;;11828;11795:139;;;-1:-1:-1;11953:6:8;;11049:916;-1:-1:-1;;;;;11049:916:8:o;12294:284::-;12352:6;12405:2;12393:9;12384:7;12380:23;12376:32;12373:52;;;12421:1;12418;12411:12;12373:52;12460:9;12447:23;12510:18;12503:5;12499:30;12492:5;12489:41;12479:69;;12544:1;12541;12534:12;12583:276;12641:6;12694:2;12682:9;12673:7;12669:23;12665:32;12662:52;;;12710:1;12707;12700:12;12662:52;12749:9;12736:23;12799:10;12792:5;12788:22;12781:5;12778:33;12768:61;;12825:1;12822;12815:12;13419:580;13496:4;13502:6;13562:11;13549:25;13652:66;13641:8;13625:14;13621:29;13617:102;13597:18;13593:127;13583:155;;13734:1;13731;13724:12;13583:155;13761:33;;13813:20;;;-1:-1:-1;13856:18:8;13845:30;;13842:50;;;13888:1;13885;13878:12;13842:50;13921:4;13909:17;;-1:-1:-1;13952:14:8;13948:27;;;13938:38;;13935:58;;;13989:1;13986;13979:12;13935:58;13419:580;;;;;:::o;14004:385::-;14099:4;14157:11;14144:25;14247:66;14236:8;14220:14;14216:29;14212:102;14192:18;14188:127;14178:155;;14329:1;14326;14319:12;14178:155;14350:33;;;;;14004:385;-1:-1:-1;;14004:385:8:o;14394:271::-;14577:6;14569;14564:3;14551:33;14533:3;14603:16;;14628:13;;;14603:16;14394:271;-1:-1:-1;14394:271:8:o;14670:604::-;14763:4;14769:6;14829:11;14816:25;14919:66;14908:8;14892:14;14888:29;14884:102;14864:18;14860:127;14850:155;;15001:1;14998;14991:12;14850:155;15028:33;;15080:20;;;-1:-1:-1;15123:18:8;15112:30;;15109:50;;;15155:1;15152;15145:12;15109:50;15188:4;15176:17;;-1:-1:-1;15239:1:8;15235:14;;;15219;15215:35;15205:46;;15202:66;;;15264:1;15261;15254:12;15279:377;15533:3;15518:19;;15546:43;15522:9;15571:6;15546:43;:::i;:::-;15598:52;15646:2;15635:9;15631:18;15623:6;15598:52;:::i;15661:128::-;15728:9;;;15749:11;;;15746:37;;;15763:18;;:::i;15794:184::-;15846:77;15843:1;15836:88;15943:4;15940:1;15933:15;15967:4;15964:1;15957:15;15983:120;16023:1;16049;16039:35;;16054:18;;:::i;:::-;-1:-1:-1;16088:9:8;;15983:120::o;16108:241::-;16288:2;16273:18;;16300:43;16277:9;16325:6;16300:43;:::i;16354:601::-;16605:3;16590:19;;16594:9;16686:6;16563:4;16720:168;16734:4;16731:1;16728:11;16720:168;;;16793:13;;16781:26;;16836:4;16827:14;;;;16876:1;16864:14;;;;16747:9;16720:168;;;16724:3;;;16897:52;16945:2;16934:9;16930:18;16922:6;16897:52;:::i;17147:288::-;17322:6;17311:9;17304:25;17365:2;17360;17349:9;17345:18;17338:30;17285:4;17385:44;17425:2;17414:9;17410:18;17402:6;17385:44;:::i;17440:638::-;17846:3;17831:19;;17859:43;17835:9;17884:6;17859:43;:::i;:::-;17952:2;17944:6;17939:2;17928:9;17924:18;17911:44;17964:53;18012:3;18001:9;17997:19;17989:6;17964:53;:::i;:::-;18068:3;18060:6;18054:3;18043:9;18039:19;18026:46;17440:638;;;;;;;:::o;18083:164::-;18159:13;;18208;;18201:21;18191:32;;18181:60;;18237:1;18234;18227:12;18181:60;18083:164;;;:::o;18252:281::-;18325:6;18333;18386:2;18374:9;18365:7;18361:23;18357:32;18354:52;;;18402:1;18399;18392:12;18354:52;18425:37;18452:9;18425:37;:::i;:::-;18415:47;;18481:46;18523:2;18512:9;18508:18;18481:46;:::i;:::-;18471:56;;18252:281;;;;;:::o;18538:112::-;18570:1;18596;18586:35;;18601:18;;:::i;:::-;-1:-1:-1;18635:9:8;;18538:112::o
Swarm Source
none
Loading...
Loading
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.