Source Code
Latest 25 from a total of 786 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Unsubscribe | 23713672 | 21 days ago | IN | 0 ETH | 0.00010826 | ||||
| Update Code Hash... | 23455640 | 57 days ago | IN | 0 ETH | 0.00006754 | ||||
| Update Code Hash... | 23455637 | 57 days ago | IN | 0 ETH | 0.00017314 | ||||
| Update Operators | 23455629 | 57 days ago | IN | 0 ETH | 0.00011418 | ||||
| Unsubscribe | 23455625 | 57 days ago | IN | 0 ETH | 0.00097118 | ||||
| Register And Sub... | 23455623 | 57 days ago | IN | 0 ETH | 0.00018139 | ||||
| Unregister | 23455597 | 57 days ago | IN | 0 ETH | 0.00005197 | ||||
| Update Operators | 23455594 | 57 days ago | IN | 0 ETH | 0.00019141 | ||||
| Update Operators | 23455524 | 57 days ago | IN | 0 ETH | 0.00011771 | ||||
| Unsubscribe | 23455520 | 57 days ago | IN | 0 ETH | 0.0010054 | ||||
| Register And Sub... | 23455515 | 57 days ago | IN | 0 ETH | 0.00018603 | ||||
| Unregister | 23455507 | 57 days ago | IN | 0 ETH | 0.00005238 | ||||
| Update Operators | 23455498 | 57 days ago | IN | 0 ETH | 0.00019241 | ||||
| Update Code Hash... | 23450365 | 57 days ago | IN | 0 ETH | 0.00006547 | ||||
| Update Operators | 23450358 | 57 days ago | IN | 0 ETH | 0.0000966 | ||||
| Unsubscribe | 23450352 | 57 days ago | IN | 0 ETH | 0.00038543 | ||||
| Register And Sub... | 23450349 | 57 days ago | IN | 0 ETH | 0.00017555 | ||||
| Update Code Hash... | 23450317 | 57 days ago | IN | 0 ETH | 0.00006508 | ||||
| Update Operators | 23450302 | 57 days ago | IN | 0 ETH | 0.00010832 | ||||
| Unsubscribe | 23450299 | 57 days ago | IN | 0 ETH | 0.00093245 | ||||
| Register And Sub... | 23450253 | 57 days ago | IN | 0 ETH | 0.00017585 | ||||
| Unregister | 23448880 | 58 days ago | IN | 0 ETH | 0.00009391 | ||||
| Update Operator | 23448795 | 58 days ago | IN | 0 ETH | 0.00004568 | ||||
| Register | 23448786 | 58 days ago | IN | 0 ETH | 0.00013104 | ||||
| Unregister | 23448767 | 58 days ago | IN | 0 ETH | 0.00006996 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 15907060 | 1113 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
OperatorFilterRegistry
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";
import {Ownable} from "openzeppelin-contracts/access/Ownable.sol";
import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol";
import {OperatorFilterRegistryErrorsAndEvents} from "./OperatorFilterRegistryErrorsAndEvents.sol";
/**
* @title OperatorFilterRegistry
* @notice Borrows heavily from the QQL BlacklistOperatorFilter contract:
* https://github.com/qql-art/contracts/blob/main/contracts/BlacklistOperatorFilter.sol
* @notice This contracts allows tokens or token owners to register specific addresses or codeHashes that may be
* * restricted according to the isOperatorAllowed function.
*/
contract OperatorFilterRegistry is IOperatorFilterRegistry, OperatorFilterRegistryErrorsAndEvents {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.Bytes32Set;
/// @dev initialized accounts have a nonzero codehash (see https://eips.ethereum.org/EIPS/eip-1052)
/// Note that this will also be a smart contract's codehash when making calls from its constructor.
bytes32 constant EOA_CODEHASH = keccak256("");
mapping(address => EnumerableSet.AddressSet) private _filteredOperators;
mapping(address => EnumerableSet.Bytes32Set) private _filteredCodeHashes;
mapping(address => address) private _registrations;
mapping(address => EnumerableSet.AddressSet) private _subscribers;
/**
* @notice restricts method caller to the address or EIP-173 "owner()"
*/
modifier onlyAddressOrOwner(address addr) {
if (msg.sender != addr) {
try Ownable(addr).owner() returns (address owner) {
if (msg.sender != owner) {
revert OnlyAddressOrOwner();
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert NotOwnable();
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
_;
}
/**
* @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns
* true if supplied registrant address is not registered.
*/
function isOperatorAllowed(address registrant, address operator) external view returns (bool) {
address registration = _registrations[registrant];
if (registration != address(0)) {
EnumerableSet.AddressSet storage filteredOperatorsRef;
EnumerableSet.Bytes32Set storage filteredCodeHashesRef;
filteredOperatorsRef = _filteredOperators[registration];
filteredCodeHashesRef = _filteredCodeHashes[registration];
if (filteredOperatorsRef.contains(operator)) {
revert AddressFiltered(operator);
}
if (operator.code.length > 0) {
bytes32 codeHash = operator.codehash;
if (filteredCodeHashesRef.contains(codeHash)) {
revert CodeHashFiltered(operator, codeHash);
}
}
}
return true;
}
//////////////////
// AUTH METHODS //
//////////////////
/**
* @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.
*/
function register(address registrant) external onlyAddressOrOwner(registrant) {
if (_registrations[registrant] != address(0)) {
revert AlreadyRegistered();
}
_registrations[registrant] = registrant;
emit RegistrationUpdated(registrant, true);
}
/**
* @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner.
* Note that this does not remove any filtered addresses or codeHashes.
* Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes.
*/
function unregister(address registrant) external onlyAddressOrOwner(registrant) {
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
_subscribers[registration].remove(registrant);
emit SubscriptionUpdated(registrant, registration, false);
}
_registrations[registrant] = address(0);
emit RegistrationUpdated(registrant, false);
}
/**
* @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes.
*/
function registerAndSubscribe(address registrant, address subscription) external onlyAddressOrOwner(registrant) {
address registration = _registrations[registrant];
if (registration != address(0)) {
revert AlreadyRegistered();
}
if (registrant == subscription) {
revert CannotSubscribeToSelf();
}
address subscriptionRegistration = _registrations[subscription];
if (subscriptionRegistration == address(0)) {
revert NotRegistered(subscription);
}
if (subscriptionRegistration != subscription) {
revert CannotSubscribeToRegistrantWithSubscription(subscription);
}
_registrations[registrant] = subscription;
_subscribers[subscription].add(registrant);
emit RegistrationUpdated(registrant, true);
emit SubscriptionUpdated(registrant, subscription, true);
}
/**
* @notice Registers an address with the registry and copies the filtered operators and codeHashes from another
* address without subscribing.
*/
function registerAndCopyEntries(address registrant, address registrantToCopy)
external
onlyAddressOrOwner(registrant)
{
if (registrantToCopy == registrant) {
revert CannotCopyFromSelf();
}
address registration = _registrations[registrant];
if (registration != address(0)) {
revert AlreadyRegistered();
}
address registrantRegistration = _registrations[registrantToCopy];
if (registrantRegistration == address(0)) {
revert NotRegistered(registrantToCopy);
}
_registrations[registrant] = registrant;
emit RegistrationUpdated(registrant, true);
_copyEntries(registrant, registrantToCopy);
}
/**
* @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.
*/
function updateOperator(address registrant, address operator, bool filtered)
external
onlyAddressOrOwner(registrant)
{
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
revert CannotUpdateWhileSubscribed(registration);
}
EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant];
if (!filtered) {
bool removed = filteredOperatorsRef.remove(operator);
if (!removed) {
revert AddressNotFiltered(operator);
}
} else {
bool added = filteredOperatorsRef.add(operator);
if (!added) {
revert AddressAlreadyFiltered(operator);
}
}
emit OperatorUpdated(registrant, operator, filtered);
}
/**
* @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.
*/
function updateCodeHash(address registrant, bytes32 codeHash, bool filtered)
external
onlyAddressOrOwner(registrant)
{
if (codeHash == EOA_CODEHASH) {
revert CannotFilterEOAs();
}
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
revert CannotUpdateWhileSubscribed(registration);
}
EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant];
if (!filtered) {
bool removed = filteredCodeHashesRef.remove(codeHash);
if (!removed) {
revert CodeHashNotFiltered(codeHash);
}
} else {
bool added = filteredCodeHashesRef.add(codeHash);
if (!added) {
revert CodeHashAlreadyFiltered(codeHash);
}
}
emit CodeHashUpdated(registrant, codeHash, filtered);
}
/**
* @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates.
*/
function updateOperators(address registrant, address[] calldata operators, bool filtered)
external
onlyAddressOrOwner(registrant)
{
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
revert CannotUpdateWhileSubscribed(registration);
}
EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant];
uint256 operatorsLength = operators.length;
unchecked {
if (!filtered) {
for (uint256 i = 0; i < operatorsLength; ++i) {
address operator = operators[i];
bool removed = filteredOperatorsRef.remove(operator);
if (!removed) {
revert AddressNotFiltered(operator);
}
}
} else {
for (uint256 i = 0; i < operatorsLength; ++i) {
address operator = operators[i];
bool added = filteredOperatorsRef.add(operator);
if (!added) {
revert AddressAlreadyFiltered(operator);
}
}
}
}
emit OperatorsUpdated(registrant, operators, filtered);
}
/**
* @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates.
*/
function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered)
external
onlyAddressOrOwner(registrant)
{
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
revert CannotUpdateWhileSubscribed(registration);
}
EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant];
uint256 codeHashesLength = codeHashes.length;
unchecked {
if (!filtered) {
for (uint256 i = 0; i < codeHashesLength; ++i) {
bytes32 codeHash = codeHashes[i];
bool removed = filteredCodeHashesRef.remove(codeHash);
if (!removed) {
revert CodeHashNotFiltered(codeHash);
}
}
} else {
for (uint256 i = 0; i < codeHashesLength; ++i) {
bytes32 codeHash = codeHashes[i];
if (codeHash == EOA_CODEHASH) {
revert CannotFilterEOAs();
}
bool added = filteredCodeHashesRef.add(codeHash);
if (!added) {
revert CodeHashAlreadyFiltered(codeHash);
}
}
}
}
emit CodeHashesUpdated(registrant, codeHashes, filtered);
}
/**
* @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous
* subscription if present.
* Note that accounts with subscriptions may go on to subscribe to other accounts - in this case,
* subscriptions will not be forwarded. Instead the former subscription's existing entries will still be
* used.
*/
function subscribe(address registrant, address newSubscription) external onlyAddressOrOwner(registrant) {
if (registrant == newSubscription) {
revert CannotSubscribeToSelf();
}
if (newSubscription == address(0)) {
revert CannotSubscribeToZeroAddress();
}
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration == newSubscription) {
revert AlreadySubscribed(newSubscription);
}
address newSubscriptionRegistration = _registrations[newSubscription];
if (newSubscriptionRegistration == address(0)) {
revert NotRegistered(newSubscription);
}
if (newSubscriptionRegistration != newSubscription) {
revert CannotSubscribeToRegistrantWithSubscription(newSubscription);
}
if (registration != registrant) {
_subscribers[registration].remove(registrant);
emit SubscriptionUpdated(registrant, registration, false);
}
_registrations[registrant] = newSubscription;
_subscribers[newSubscription].add(registrant);
emit SubscriptionUpdated(registrant, newSubscription, true);
}
/**
* @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.
*/
function unsubscribe(address registrant, bool copyExistingEntries) external onlyAddressOrOwner(registrant) {
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration == registrant) {
revert NotSubscribed();
}
_subscribers[registration].remove(registrant);
_registrations[registrant] = registrant;
emit SubscriptionUpdated(registrant, registration, false);
if (copyExistingEntries) {
_copyEntries(registrant, registration);
}
}
/**
* @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.
*/
function copyEntriesOf(address registrant, address registrantToCopy) external onlyAddressOrOwner(registrant) {
if (registrant == registrantToCopy) {
revert CannotCopyFromSelf();
}
address registration = _registrations[registrant];
if (registration == address(0)) {
revert NotRegistered(registrant);
}
if (registration != registrant) {
revert CannotUpdateWhileSubscribed(registration);
}
address registrantRegistration = _registrations[registrantToCopy];
if (registrantRegistration == address(0)) {
revert NotRegistered(registrantToCopy);
}
_copyEntries(registrant, registrantToCopy);
}
/// @dev helper to copy entries from registrantToCopy to registrant and emit events
function _copyEntries(address registrant, address registrantToCopy) private {
EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrantToCopy];
EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrantToCopy];
uint256 filteredOperatorsLength = filteredOperatorsRef.length();
uint256 filteredCodeHashesLength = filteredCodeHashesRef.length();
unchecked {
for (uint256 i = 0; i < filteredOperatorsLength; ++i) {
address operator = filteredOperatorsRef.at(i);
bool added = _filteredOperators[registrant].add(operator);
if (added) {
emit OperatorUpdated(registrant, operator, true);
}
}
for (uint256 i = 0; i < filteredCodeHashesLength; ++i) {
bytes32 codehash = filteredCodeHashesRef.at(i);
bool added = _filteredCodeHashes[registrant].add(codehash);
if (added) {
emit CodeHashUpdated(registrant, codehash, true);
}
}
}
}
//////////////////
// VIEW METHODS //
//////////////////
/**
* @notice Get the subscription address of a given registrant, if any.
*/
function subscriptionOf(address registrant) external view returns (address subscription) {
subscription = _registrations[registrant];
if (subscription == address(0)) {
revert NotRegistered(registrant);
} else if (subscription == registrant) {
subscription = address(0);
}
}
/**
* @notice Get the set of addresses subscribed to a given registrant.
* Note that order is not guaranteed as updates are made.
*/
function subscribers(address registrant) external view returns (address[] memory) {
return _subscribers[registrant].values();
}
/**
* @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant.
* Note that order is not guaranteed as updates are made.
*/
function subscriberAt(address registrant, uint256 index) external view returns (address) {
return _subscribers[registrant].at(index);
}
/**
* @notice Returns true if operator is filtered by a given address or its subscription.
*/
function isOperatorFiltered(address registrant, address operator) external view returns (bool) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredOperators[registration].contains(operator);
}
return _filteredOperators[registrant].contains(operator);
}
/**
* @notice Returns true if a codeHash is filtered by a given address or its subscription.
*/
function isCodeHashFiltered(address registrant, bytes32 codeHash) external view returns (bool) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredCodeHashes[registration].contains(codeHash);
}
return _filteredCodeHashes[registrant].contains(codeHash);
}
/**
* @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.
*/
function isCodeHashOfFiltered(address registrant, address operatorWithCode) external view returns (bool) {
bytes32 codeHash = operatorWithCode.codehash;
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredCodeHashes[registration].contains(codeHash);
}
return _filteredCodeHashes[registrant].contains(codeHash);
}
/**
* @notice Returns true if an address has registered
*/
function isRegistered(address registrant) external view returns (bool) {
return _registrations[registrant] != address(0);
}
/**
* @notice Returns a list of filtered operators for a given address or its subscription.
*/
function filteredOperators(address registrant) external view returns (address[] memory) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredOperators[registration].values();
}
return _filteredOperators[registrant].values();
}
/**
* @notice Returns the set of filtered codeHashes for a given address or its subscription.
* Note that order is not guaranteed as updates are made.
*/
function filteredCodeHashes(address registrant) external view returns (bytes32[] memory) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredCodeHashes[registration].values();
}
return _filteredCodeHashes[registrant].values();
}
/**
* @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or
* its subscription.
* Note that order is not guaranteed as updates are made.
*/
function filteredOperatorAt(address registrant, uint256 index) external view returns (address) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredOperators[registration].at(index);
}
return _filteredOperators[registrant].at(index);
}
/**
* @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or
* its subscription.
* Note that order is not guaranteed as updates are made.
*/
function filteredCodeHashAt(address registrant, uint256 index) external view returns (bytes32) {
address registration = _registrations[registrant];
if (registration != registrant) {
return _filteredCodeHashes[registration].at(index);
}
return _filteredCodeHashes[registrant].at(index);
}
/// @dev Convenience method to compute the code hash of an arbitrary contract
function codeHashOf(address a) external view returns (bytes32) {
return a.codehash;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol";
interface IOperatorFilterRegistry {
function isOperatorAllowed(address registrant, address operator) external returns (bool);
function register(address registrant) external;
function registerAndSubscribe(address registrant, address subscription) external;
function registerAndCopyEntries(address registrant, address registrantToCopy) external;
function updateOperator(address registrant, address operator, bool filtered) external;
function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
function subscribe(address registrant, address registrantToSubscribe) external;
function unsubscribe(address registrant, bool copyExistingEntries) external;
function subscriptionOf(address addr) external returns (address registrant);
function subscribers(address registrant) external returns (address[] memory);
function subscriberAt(address registrant, uint256 index) external returns (address);
function copyEntriesOf(address registrant, address registrantToCopy) external;
function isOperatorFiltered(address registrant, address operator) external returns (bool);
function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
function filteredOperators(address addr) external returns (address[] memory);
function filteredCodeHashes(address addr) external returns (bytes32[] memory);
function filteredOperatorAt(address registrant, uint256 index) external returns (address);
function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
function isRegistered(address addr) external returns (bool);
function codeHashOf(address addr) external returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract OperatorFilterRegistryErrorsAndEvents {
error CannotFilterEOAs();
error AddressAlreadyFiltered(address operator);
error AddressNotFiltered(address operator);
error CodeHashAlreadyFiltered(bytes32 codeHash);
error CodeHashNotFiltered(bytes32 codeHash);
error OnlyAddressOrOwner();
error NotRegistered(address registrant);
error AlreadyRegistered();
error AlreadySubscribed(address subscription);
error NotSubscribed();
error CannotUpdateWhileSubscribed(address subscription);
error CannotSubscribeToSelf();
error CannotSubscribeToZeroAddress();
error NotOwnable();
error AddressFiltered(address filtered);
error CodeHashFiltered(address account, bytes32 codeHash);
error CannotSubscribeToRegistrantWithSubscription(address registrant);
error CannotCopyFromSelf();
event RegistrationUpdated(address indexed registrant, bool indexed registered);
event OperatorUpdated(address indexed registrant, address indexed operator, bool indexed filtered);
event OperatorsUpdated(address indexed registrant, address[] operators, bool indexed filtered);
event CodeHashUpdated(address indexed registrant, bytes32 indexed codeHash, bool indexed filtered);
event CodeHashesUpdated(address indexed registrant, bytes32[] codeHashes, bool indexed filtered);
event SubscriptionUpdated(address indexed registrant, address indexed subscription, bool indexed subscribed);
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"AddressAlreadyFiltered","type":"error"},{"inputs":[{"internalType":"address","name":"filtered","type":"address"}],"name":"AddressFiltered","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"AddressNotFiltered","type":"error"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[{"internalType":"address","name":"subscription","type":"address"}],"name":"AlreadySubscribed","type":"error"},{"inputs":[],"name":"CannotCopyFromSelf","type":"error"},{"inputs":[],"name":"CannotFilterEOAs","type":"error"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"CannotSubscribeToRegistrantWithSubscription","type":"error"},{"inputs":[],"name":"CannotSubscribeToSelf","type":"error"},{"inputs":[],"name":"CannotSubscribeToZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"subscription","type":"address"}],"name":"CannotUpdateWhileSubscribed","type":"error"},{"inputs":[{"internalType":"bytes32","name":"codeHash","type":"bytes32"}],"name":"CodeHashAlreadyFiltered","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"codeHash","type":"bytes32"}],"name":"CodeHashFiltered","type":"error"},{"inputs":[{"internalType":"bytes32","name":"codeHash","type":"bytes32"}],"name":"CodeHashNotFiltered","type":"error"},{"inputs":[],"name":"NotOwnable","type":"error"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"NotRegistered","type":"error"},{"inputs":[],"name":"NotSubscribed","type":"error"},{"inputs":[],"name":"OnlyAddressOrOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":true,"internalType":"bytes32","name":"codeHash","type":"bytes32"},{"indexed":true,"internalType":"bool","name":"filtered","type":"bool"}],"name":"CodeHashUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":false,"internalType":"bytes32[]","name":"codeHashes","type":"bytes32[]"},{"indexed":true,"internalType":"bool","name":"filtered","type":"bool"}],"name":"CodeHashesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"bool","name":"filtered","type":"bool"}],"name":"OperatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":false,"internalType":"address[]","name":"operators","type":"address[]"},{"indexed":true,"internalType":"bool","name":"filtered","type":"bool"}],"name":"OperatorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":true,"internalType":"bool","name":"registered","type":"bool"}],"name":"RegistrationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registrant","type":"address"},{"indexed":true,"internalType":"address","name":"subscription","type":"address"},{"indexed":true,"internalType":"bool","name":"subscribed","type":"bool"}],"name":"SubscriptionUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"a","type":"address"}],"name":"codeHashOf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"registrantToCopy","type":"address"}],"name":"copyEntriesOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"filteredCodeHashAt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"filteredCodeHashes","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"filteredOperatorAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"filteredOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"bytes32","name":"codeHash","type":"bytes32"}],"name":"isCodeHashFiltered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"operatorWithCode","type":"address"}],"name":"isCodeHashOfFiltered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorFiltered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"isRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"registrantToCopy","type":"address"}],"name":"registerAndCopyEntries","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"subscription","type":"address"}],"name":"registerAndSubscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"newSubscription","type":"address"}],"name":"subscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"subscriberAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"subscribers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"subscriptionOf","outputs":[{"internalType":"address","name":"subscription","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"}],"name":"unregister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"bool","name":"copyExistingEntries","type":"bool"}],"name":"unsubscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"bytes32","name":"codeHash","type":"bytes32"},{"internalType":"bool","name":"filtered","type":"bool"}],"name":"updateCodeHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"bytes32[]","name":"codeHashes","type":"bytes32[]"},{"internalType":"bool","name":"filtered","type":"bool"}],"name":"updateCodeHashes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"filtered","type":"bool"}],"name":"updateOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"},{"internalType":"bool","name":"filtered","type":"bool"}],"name":"updateOperators","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50613848806100206000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063712fc00b116100e3578063b314d4141161008c578063c430880511610066578063c4308805146103d1578063c6171134146103e4578063e4aecb54146103f757600080fd5b8063b314d4141461035b578063bbd652c71461036e578063c3c5a5471461039657600080fd5b8063a14584c1116100bd578063a14584c114610314578063a2f367ab14610327578063a6529eb51461033a57600080fd5b8063712fc00b146102db5780637d3e3dbe146102ee578063a0af29031461030157600080fd5b80633f1cc5fa116101455780635745ae281161011f5780635745ae28146102855780635eae3173146102a55780636af0c315146102c857600080fd5b80633f1cc5fa1461024c5780634420e4861461025f57806355940e511461027257600080fd5b80632ec2c246116101765780632ec2c246146101ee57806334a0dc10146102015780633c5030bb1461021457600080fd5b8063063298b61461019d5780631e06b4b4146101b257806322fa2762146101c5575b600080fd5b6101b06101ab366004613484565b61040a565b005b6101b06101c03660046134eb565b610854565b6101d86101d3366004613524565b610b57565b6040516101e59190613541565b60405180910390f35b6101b06101fc366004613524565b610bec565b6101b061020f366004613585565b610eaa565b610227610222366004613524565b611168565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e5565b61022761025a3660046135ba565b61121b565b6101b061026d366004613524565b6112bc565b6102276102803660046135ba565b6114b7565b610298610293366004613524565b6114e6565b6040516101e591906135e6565b6102b86102b33660046134eb565b611517565b60405190151581526020016101e5565b6102b86102d63660046135ba565b6115be565b6101b06102e9366004613634565b61164d565b6101b06102fc3660046134eb565b6119cd565b6101b061030f3660046134eb565b611da3565b6101b0610322366004613484565b612081565b6101b0610335366004613672565b61244f565b61034d6103483660046135ba565b6127b6565b6040519081526020016101e5565b6101b06103693660046134eb565b612845565b61034d61037c366004613524565b73ffffffffffffffffffffffffffffffffffffffff163f90565b6102b86103a4366004613524565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6102986103df366004613524565b612d63565b6102b86103f23660046134eb565b612df1565b6102b86104053660046134eb565b612f4c565b833373ffffffffffffffffffffffffffffffffffffffff821614610575578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104ad575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104aa918101906136b0565b60015b610524573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b606091505b50805160000361051c576040517fb2c1414000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b3373ffffffffffffffffffffffffffffffffffffffff821614610573576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80861660009081526002602052604090205416806105f1576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024015b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461066e576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260016020526040902084846107225760005b8181101561071c5760008888838181106106b8576106b86136cd565b90506020020135905060006106d68286612fdb90919063ffffffff16565b905080610712576040517f478730a8000000000000000000000000000000000000000000000000000000008152600481018390526024016105e8565b505060010161069c565b506107f7565b60005b818110156107f5576000888883818110610741576107416136cd565b9050602002013590507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081036107a3576040517ff575ead800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107af8583612fe7565b9050806107eb576040517f186bea00000000000000000000000000000000000000000000000000000000008152600481018390526024016105e8565b5050600101610725565b505b8415158873ffffffffffffffffffffffffffffffffffffffff167f34e9f70c5a16a4df2a396cf0cbc4735eb3c7fb6ae40aaa0b34be7720121d1b9689896040516108429291906136fc565b60405180910390a35050505050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614610976578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156108f7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526108f4918101906136b0565b60015b610925573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610974576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036109db576040517f1acab6b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680610a52576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acf576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680610b46576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b610b508585612ff3565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526002602052604090205460609216908114610bbe5773ffffffffffffffffffffffffffffffffffffffff81166000908152600160205260409020610bb79061318d565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020610bb79061318d565b803373ffffffffffffffffffffffffffffffffffffffff821614610d0e578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610c8f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610c8c918101906136b0565b60015b610cbd573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610d0c576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020541680610d85576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016105e8565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610e305773ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020610de7908461319a565b5060405160009073ffffffffffffffffffffffffffffffffffffffff80841691908616907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a45b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519091907f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59908390a3505050565b813373ffffffffffffffffffffffffffffffffffffffff821614610fcc578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610f4d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610f4a918101906136b0565b60015b610f7b573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610fca576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680611043576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110a8576040517f237e6c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604090206110d7908561319a565b5073ffffffffffffffffffffffffffffffffffffffff80851660008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055519092841691907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a48215611162576111628482612ff3565b50505050565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526002602052604090205416806111df576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611216575060005b919050565b73ffffffffffffffffffffffffffffffffffffffff8083166000818152600260205260408120549092169081146112835773ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902061127b90846131bc565b9150506112b6565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090206112b290846131bc565b9150505b92915050565b803373ffffffffffffffffffffffffffffffffffffffff8216146113de578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561135f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261135c918101906136b0565b60015b61138d573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff8216146113dc576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff828116600090815260026020526040902054161561143d576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551600192917f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5991a35050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120610bb790836131bc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604090206060906112b69061318d565b73ffffffffffffffffffffffffffffffffffffffff82811660008181526002602052604081205490928085163f9291169081146115865773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061157d90836131c8565b925050506112b6565b73ffffffffffffffffffffffffffffffffffffffff851660009081526001602052604090206115b590836131c8565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff80831660008181526002602052604081205490921690811461161e5773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061127b90846131c8565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604090206112b290846131c8565b823373ffffffffffffffffffffffffffffffffffffffff82161461176f578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156116f0575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526116ed918101906136b0565b60015b61171e573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff82161461176d576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47083036117c8576040517ff575ead800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808516600090815260026020526040902054168061183f576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118bc576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600160205260409020836119345760006118f28287612fdb565b90508061192e576040517f478730a8000000000000000000000000000000000000000000000000000000008152600481018790526024016105e8565b5061197e565b60006119408287612fe7565b90508061197c576040517f186bea00000000000000000000000000000000000000000000000000000000008152600481018790526024016105e8565b505b831515858773ffffffffffffffffffffffffffffffffffffffff167fb8036058bafea884aabc446ca15619fd86f5464a4ad96f64164ad6f77444354d60405160405180910390a4505050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614611aef578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611a70575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a6d918101906136b0565b60015b611a9e573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614611aed576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020526040902054168015611b4f576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bb4576040517f347f118f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680611c2b576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ca8576040517f768e549c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff858116600090815260026020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694891694851790559282526003905220611d0f90866131e0565b5060405160019073ffffffffffffffffffffffffffffffffffffffff8716907f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5990600090a360405160019073ffffffffffffffffffffffffffffffffffffffff80871691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e890600090a45050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614611ec5578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611e46575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611e43918101906136b0565b60015b611e74573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614611ec3576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f2a576040517f1acab6b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020526040902054168015611f8a576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612001576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff851660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551600192917f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5991a3610b508585612ff3565b833373ffffffffffffffffffffffffffffffffffffffff8216146121a3578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612124575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612121918101906136b0565b60015b612152573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff8216146121a1576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff808616600090815260026020526040902054168061221a576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612297576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902084846123655760005b8181101561235f5760008888838181106122e1576122e16136cd565b90506020020160208101906122f69190613524565b90506000612304858361319a565b905080612355576040517f45525c0e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b50506001016122c5565b50612404565b60005b81811015612402576000888883818110612384576123846136cd565b90506020020160208101906123999190613524565b905060006123a785836131e0565b9050806123f8576040517f0bb4423400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b5050600101612368565b505b8415158873ffffffffffffffffffffffffffffffffffffffff167f02b85afdacb82d5512c6f05566b3018677ffcbd7e5f75e498bc64081131cbd6c898960405161084292919061374e565b823373ffffffffffffffffffffffffffffffffffffffff821614612571578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156124f2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526124ef918101906136b0565b60015b612520573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff82161461256f576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80851660009081526002602052604090205416806125e8576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612665576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020836126f257600061269b828761319a565b9050806126ec576040517f45525c0e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b50612751565b60006126fe82876131e0565b90508061274f576040517f0bb4423400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b505b8315158573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f2738289d9deecdc30eb8ffc42876633caecca1ffa166e4efa89f408e17373a1a60405160405180910390a4505050505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000818152600260205260408120549092169081146128165773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061127b90846131bc565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604090206112b290846131bc565b813373ffffffffffffffffffffffffffffffffffffffff821614612967578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156128e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526128e5918101906136b0565b60015b612916573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614612965576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129cc576040517f347f118f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612a19576040517fb05574d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612a90576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b0d576040517f73a4164900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612b84576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612c01576040517f768e549c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612cac5773ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020612c63908661319a565b5060405160009073ffffffffffffffffffffffffffffffffffffffff80851691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a45b73ffffffffffffffffffffffffffffffffffffffff858116600090815260026020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694891694851790559282526003905220612d1390866131e0565b5060405160019073ffffffffffffffffffffffffffffffffffffffff80871691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e890600090a45050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526002602052604090205460609216908114612dc35773ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020610bb79061318d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020610bb79061318d565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260408120549091168015612f425773ffffffffffffffffffffffffffffffffffffffff81166000908152602081815260408083206001909252909120612e598286613202565b15612ea8576040517fa8cf495d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85163b15612f3f5773ffffffffffffffffffffffffffffffffffffffff85163f612ee782826131c8565b15612f3d576040517f5f3853a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87166004820152602481018290526044016105e8565b505b50505b5060019392505050565b73ffffffffffffffffffffffffffffffffffffffff808316600081815260026020526040812054909216908114612fac5773ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902061127b9084613202565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090206112b29084613202565b6000610bb78383613231565b6000610bb78383613324565b73ffffffffffffffffffffffffffffffffffffffff811660009081526020818152604080832060019092528220909161302b83613373565b9050600061303883613373565b905060005b828110156130e057600061305186836131bc565b73ffffffffffffffffffffffffffffffffffffffff891660009081526020819052604081209192509061308490836131e0565b905080156130d65760405160019073ffffffffffffffffffffffffffffffffffffffff80851691908c16907f2738289d9deecdc30eb8ffc42876633caecca1ffa166e4efa89f408e17373a1a90600090a45b505060010161303d565b5060005b818110156131845760006130f885836131bc565b73ffffffffffffffffffffffffffffffffffffffff891660009081526001602052604081209192509061312b9083612fe7565b9050801561317a57604051600190839073ffffffffffffffffffffffffffffffffffffffff8c16907fb8036058bafea884aabc446ca15619fd86f5464a4ad96f64164ad6f77444354d90600090a45b50506001016130e4565b50505050505050565b60606000610bb78361337d565b6000610bb78373ffffffffffffffffffffffffffffffffffffffff8416613231565b6000610bb783836133d9565b60008181526001830160205260408120541515610bb7565b6000610bb78373ffffffffffffffffffffffffffffffffffffffff8416613324565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bb7565b6000818152600183016020526040812054801561331a5760006132556001836137a9565b8554909150600090613269906001906137a9565b90508181146132ce576000866000018281548110613289576132896136cd565b90600052602060002001549050808760000184815481106132ac576132ac6136cd565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806132df576132df6137e3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112b6565b60009150506112b6565b600081815260018301602052604081205461336b575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112b6565b5060006112b6565b60006112b6825490565b6060816000018054806020026020016040519081016040528092919081815260200182805480156133cd57602002820191906000526020600020905b8154815260200190600101908083116133b9575b50505050509050919050565b60008260000182815481106133f0576133f06136cd565b9060005260206000200154905092915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461342557600080fd5b50565b60008083601f84011261343a57600080fd5b50813567ffffffffffffffff81111561345257600080fd5b6020830191508360208260051b850101111561346d57600080fd5b9250929050565b8035801515811461121657600080fd5b6000806000806060858703121561349a57600080fd5b84356134a581613403565b9350602085013567ffffffffffffffff8111156134c157600080fd5b6134cd87828801613428565b90945092506134e0905060408601613474565b905092959194509250565b600080604083850312156134fe57600080fd5b823561350981613403565b9150602083013561351981613403565b809150509250929050565b60006020828403121561353657600080fd5b8135610bb781613403565b6020808252825182820181905260009190848201906040850190845b818110156135795783518352928401929184019160010161355d565b50909695505050505050565b6000806040838503121561359857600080fd5b82356135a381613403565b91506135b160208401613474565b90509250929050565b600080604083850312156135cd57600080fd5b82356135d881613403565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b8181101561357957835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613602565b60008060006060848603121561364957600080fd5b833561365481613403565b92506020840135915061366960408501613474565b90509250925092565b60008060006060848603121561368757600080fd5b833561369281613403565b925060208401356136a281613403565b915061366960408501613474565b6000602082840312156136c257600080fd5b8151610bb781613403565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561373557600080fd5b8260051b80856040850137919091016040019392505050565b60208082528181018390526000908460408401835b8681101561379e57823561377681613403565b73ffffffffffffffffffffffffffffffffffffffff1682529183019190830190600101613763565b509695505050505050565b818103818111156112b6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220d2eb4529f96412ccc09b0c0c04d7ff105932b0b691aea14b7aa158442949a08664736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063712fc00b116100e3578063b314d4141161008c578063c430880511610066578063c4308805146103d1578063c6171134146103e4578063e4aecb54146103f757600080fd5b8063b314d4141461035b578063bbd652c71461036e578063c3c5a5471461039657600080fd5b8063a14584c1116100bd578063a14584c114610314578063a2f367ab14610327578063a6529eb51461033a57600080fd5b8063712fc00b146102db5780637d3e3dbe146102ee578063a0af29031461030157600080fd5b80633f1cc5fa116101455780635745ae281161011f5780635745ae28146102855780635eae3173146102a55780636af0c315146102c857600080fd5b80633f1cc5fa1461024c5780634420e4861461025f57806355940e511461027257600080fd5b80632ec2c246116101765780632ec2c246146101ee57806334a0dc10146102015780633c5030bb1461021457600080fd5b8063063298b61461019d5780631e06b4b4146101b257806322fa2762146101c5575b600080fd5b6101b06101ab366004613484565b61040a565b005b6101b06101c03660046134eb565b610854565b6101d86101d3366004613524565b610b57565b6040516101e59190613541565b60405180910390f35b6101b06101fc366004613524565b610bec565b6101b061020f366004613585565b610eaa565b610227610222366004613524565b611168565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e5565b61022761025a3660046135ba565b61121b565b6101b061026d366004613524565b6112bc565b6102276102803660046135ba565b6114b7565b610298610293366004613524565b6114e6565b6040516101e591906135e6565b6102b86102b33660046134eb565b611517565b60405190151581526020016101e5565b6102b86102d63660046135ba565b6115be565b6101b06102e9366004613634565b61164d565b6101b06102fc3660046134eb565b6119cd565b6101b061030f3660046134eb565b611da3565b6101b0610322366004613484565b612081565b6101b0610335366004613672565b61244f565b61034d6103483660046135ba565b6127b6565b6040519081526020016101e5565b6101b06103693660046134eb565b612845565b61034d61037c366004613524565b73ffffffffffffffffffffffffffffffffffffffff163f90565b6102b86103a4366004613524565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6102986103df366004613524565b612d63565b6102b86103f23660046134eb565b612df1565b6102b86104053660046134eb565b612f4c565b833373ffffffffffffffffffffffffffffffffffffffff821614610575578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104ad575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104aa918101906136b0565b60015b610524573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b606091505b50805160000361051c576040517fb2c1414000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b3373ffffffffffffffffffffffffffffffffffffffff821614610573576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80861660009081526002602052604090205416806105f1576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024015b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461066e576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260016020526040902084846107225760005b8181101561071c5760008888838181106106b8576106b86136cd565b90506020020135905060006106d68286612fdb90919063ffffffff16565b905080610712576040517f478730a8000000000000000000000000000000000000000000000000000000008152600481018390526024016105e8565b505060010161069c565b506107f7565b60005b818110156107f5576000888883818110610741576107416136cd565b9050602002013590507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081036107a3576040517ff575ead800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107af8583612fe7565b9050806107eb576040517f186bea00000000000000000000000000000000000000000000000000000000008152600481018390526024016105e8565b5050600101610725565b505b8415158873ffffffffffffffffffffffffffffffffffffffff167f34e9f70c5a16a4df2a396cf0cbc4735eb3c7fb6ae40aaa0b34be7720121d1b9689896040516108429291906136fc565b60405180910390a35050505050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614610976578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156108f7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526108f4918101906136b0565b60015b610925573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610974576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036109db576040517f1acab6b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680610a52576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acf576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680610b46576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b610b508585612ff3565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526002602052604090205460609216908114610bbe5773ffffffffffffffffffffffffffffffffffffffff81166000908152600160205260409020610bb79061318d565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020610bb79061318d565b803373ffffffffffffffffffffffffffffffffffffffff821614610d0e578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610c8f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610c8c918101906136b0565b60015b610cbd573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610d0c576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020541680610d85576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016105e8565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610e305773ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020610de7908461319a565b5060405160009073ffffffffffffffffffffffffffffffffffffffff80841691908616907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a45b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519091907f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb59908390a3505050565b813373ffffffffffffffffffffffffffffffffffffffff821614610fcc578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610f4d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610f4a918101906136b0565b60015b610f7b573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614610fca576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680611043576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110a8576040517f237e6c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604090206110d7908561319a565b5073ffffffffffffffffffffffffffffffffffffffff80851660008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055519092841691907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a48215611162576111628482612ff3565b50505050565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526002602052604090205416806111df576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611216575060005b919050565b73ffffffffffffffffffffffffffffffffffffffff8083166000818152600260205260408120549092169081146112835773ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902061127b90846131bc565b9150506112b6565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090206112b290846131bc565b9150505b92915050565b803373ffffffffffffffffffffffffffffffffffffffff8216146113de578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561135f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261135c918101906136b0565b60015b61138d573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff8216146113dc576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff828116600090815260026020526040902054161561143d576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551600192917f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5991a35050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120610bb790836131bc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604090206060906112b69061318d565b73ffffffffffffffffffffffffffffffffffffffff82811660008181526002602052604081205490928085163f9291169081146115865773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061157d90836131c8565b925050506112b6565b73ffffffffffffffffffffffffffffffffffffffff851660009081526001602052604090206115b590836131c8565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff80831660008181526002602052604081205490921690811461161e5773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061127b90846131c8565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604090206112b290846131c8565b823373ffffffffffffffffffffffffffffffffffffffff82161461176f578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156116f0575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526116ed918101906136b0565b60015b61171e573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff82161461176d576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47083036117c8576040517ff575ead800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808516600090815260026020526040902054168061183f576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118bc576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600160205260409020836119345760006118f28287612fdb565b90508061192e576040517f478730a8000000000000000000000000000000000000000000000000000000008152600481018790526024016105e8565b5061197e565b60006119408287612fe7565b90508061197c576040517f186bea00000000000000000000000000000000000000000000000000000000008152600481018790526024016105e8565b505b831515858773ffffffffffffffffffffffffffffffffffffffff167fb8036058bafea884aabc446ca15619fd86f5464a4ad96f64164ad6f77444354d60405160405180910390a4505050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614611aef578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611a70575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611a6d918101906136b0565b60015b611a9e573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614611aed576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020526040902054168015611b4f576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bb4576040517f347f118f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680611c2b576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ca8576040517f768e549c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff858116600090815260026020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694891694851790559282526003905220611d0f90866131e0565b5060405160019073ffffffffffffffffffffffffffffffffffffffff8716907f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5990600090a360405160019073ffffffffffffffffffffffffffffffffffffffff80871691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e890600090a45050505050565b813373ffffffffffffffffffffffffffffffffffffffff821614611ec5578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611e46575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611e43918101906136b0565b60015b611e74573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614611ec3576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f2a576040517f1acab6b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020526040902054168015611f8a576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612001576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff851660008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551600192917f86d03f430c7616021073d7a71766f632f1ce19f289aa989534d9f4732253eb5991a3610b508585612ff3565b833373ffffffffffffffffffffffffffffffffffffffff8216146121a3578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612124575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612121918101906136b0565b60015b612152573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff8216146121a1576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff808616600090815260026020526040902054168061221a576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b8573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612297576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902084846123655760005b8181101561235f5760008888838181106122e1576122e16136cd565b90506020020160208101906122f69190613524565b90506000612304858361319a565b905080612355576040517f45525c0e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b50506001016122c5565b50612404565b60005b81811015612402576000888883818110612384576123846136cd565b90506020020160208101906123999190613524565b905060006123a785836131e0565b9050806123f8576040517f0bb4423400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105e8565b5050600101612368565b505b8415158873ffffffffffffffffffffffffffffffffffffffff167f02b85afdacb82d5512c6f05566b3018677ffcbd7e5f75e498bc64081131cbd6c898960405161084292919061374e565b823373ffffffffffffffffffffffffffffffffffffffff821614612571578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156124f2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526124ef918101906136b0565b60015b612520573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff82161461256f576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80851660009081526002602052604090205416806125e8576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612665576040517f04af4d6900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020836126f257600061269b828761319a565b9050806126ec576040517f45525c0e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b50612751565b60006126fe82876131e0565b90508061274f576040517f0bb4423400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871660048201526024016105e8565b505b8315158573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f2738289d9deecdc30eb8ffc42876633caecca1ffa166e4efa89f408e17373a1a60405160405180910390a4505050505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000818152600260205260408120549092169081146128165773ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902061127b90846131bc565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604090206112b290846131bc565b813373ffffffffffffffffffffffffffffffffffffffff821614612967578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156128e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526128e5918101906136b0565b60015b612916573d8080156104db576040519150601f19603f3d011682016040523d82523d6000602084013e6104e0565b3373ffffffffffffffffffffffffffffffffffffffff821614612965576040517ffcf5eff800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129cc576040517f347f118f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612a19576040517fb05574d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612a90576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b0d576040517f73a4164900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600260205260409020541680612b84576040517fbfc6c33700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612c01576040517f768e549c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105e8565b8473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612cac5773ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020612c63908661319a565b5060405160009073ffffffffffffffffffffffffffffffffffffffff80851691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e8908490a45b73ffffffffffffffffffffffffffffffffffffffff858116600090815260026020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694891694851790559282526003905220612d1390866131e0565b5060405160019073ffffffffffffffffffffffffffffffffffffffff80871691908816907e38c54977604f1a5c0a3604cbbecd0153c81e3131799ead95755e8bb5d5b9e890600090a45050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526002602052604090205460609216908114612dc35773ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020610bb79061318d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020610bb79061318d565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260408120549091168015612f425773ffffffffffffffffffffffffffffffffffffffff81166000908152602081815260408083206001909252909120612e598286613202565b15612ea8576040517fa8cf495d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024016105e8565b73ffffffffffffffffffffffffffffffffffffffff85163b15612f3f5773ffffffffffffffffffffffffffffffffffffffff85163f612ee782826131c8565b15612f3d576040517f5f3853a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87166004820152602481018290526044016105e8565b505b50505b5060019392505050565b73ffffffffffffffffffffffffffffffffffffffff808316600081815260026020526040812054909216908114612fac5773ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902061127b9084613202565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090206112b29084613202565b6000610bb78383613231565b6000610bb78383613324565b73ffffffffffffffffffffffffffffffffffffffff811660009081526020818152604080832060019092528220909161302b83613373565b9050600061303883613373565b905060005b828110156130e057600061305186836131bc565b73ffffffffffffffffffffffffffffffffffffffff891660009081526020819052604081209192509061308490836131e0565b905080156130d65760405160019073ffffffffffffffffffffffffffffffffffffffff80851691908c16907f2738289d9deecdc30eb8ffc42876633caecca1ffa166e4efa89f408e17373a1a90600090a45b505060010161303d565b5060005b818110156131845760006130f885836131bc565b73ffffffffffffffffffffffffffffffffffffffff891660009081526001602052604081209192509061312b9083612fe7565b9050801561317a57604051600190839073ffffffffffffffffffffffffffffffffffffffff8c16907fb8036058bafea884aabc446ca15619fd86f5464a4ad96f64164ad6f77444354d90600090a45b50506001016130e4565b50505050505050565b60606000610bb78361337d565b6000610bb78373ffffffffffffffffffffffffffffffffffffffff8416613231565b6000610bb783836133d9565b60008181526001830160205260408120541515610bb7565b6000610bb78373ffffffffffffffffffffffffffffffffffffffff8416613324565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bb7565b6000818152600183016020526040812054801561331a5760006132556001836137a9565b8554909150600090613269906001906137a9565b90508181146132ce576000866000018281548110613289576132896136cd565b90600052602060002001549050808760000184815481106132ac576132ac6136cd565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806132df576132df6137e3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112b6565b60009150506112b6565b600081815260018301602052604081205461336b575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112b6565b5060006112b6565b60006112b6825490565b6060816000018054806020026020016040519081016040528092919081815260200182805480156133cd57602002820191906000526020600020905b8154815260200190600101908083116133b9575b50505050509050919050565b60008260000182815481106133f0576133f06136cd565b9060005260206000200154905092915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461342557600080fd5b50565b60008083601f84011261343a57600080fd5b50813567ffffffffffffffff81111561345257600080fd5b6020830191508360208260051b850101111561346d57600080fd5b9250929050565b8035801515811461121657600080fd5b6000806000806060858703121561349a57600080fd5b84356134a581613403565b9350602085013567ffffffffffffffff8111156134c157600080fd5b6134cd87828801613428565b90945092506134e0905060408601613474565b905092959194509250565b600080604083850312156134fe57600080fd5b823561350981613403565b9150602083013561351981613403565b809150509250929050565b60006020828403121561353657600080fd5b8135610bb781613403565b6020808252825182820181905260009190848201906040850190845b818110156135795783518352928401929184019160010161355d565b50909695505050505050565b6000806040838503121561359857600080fd5b82356135a381613403565b91506135b160208401613474565b90509250929050565b600080604083850312156135cd57600080fd5b82356135d881613403565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b8181101561357957835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613602565b60008060006060848603121561364957600080fd5b833561365481613403565b92506020840135915061366960408501613474565b90509250925092565b60008060006060848603121561368757600080fd5b833561369281613403565b925060208401356136a281613403565b915061366960408501613474565b6000602082840312156136c257600080fd5b8151610bb781613403565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561373557600080fd5b8260051b80856040850137919091016040019392505050565b60208082528181018390526000908460408401835b8681101561379e57823561377681613403565b73ffffffffffffffffffffffffffffffffffffffff1682529183019190830190600101613763565b509695505050505050565b818103818111156112b6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220d2eb4529f96412ccc09b0c0c04d7ff105932b0b691aea14b7aa158442949a08664736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ARB | 100.00% | $0.204977 | 1 | $0.2049 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.