Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EAS
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { EIP1271Verifier } from "src/EAS/eip1271/EIP1271Verifier.sol";
import { ISchemaResolver } from "src/EAS/resolver/ISchemaResolver.sol";
import {
AccessDenied,
EMPTY_UID,
Signature,
InvalidLength,
MAX_GAP,
NotFound,
NO_EXPIRATION_TIME,
uncheckedInc
} from "src/EAS/Common.sol";
import {
Attestation,
AttestationRequest,
AttestationRequestData,
DelegatedAttestationRequest,
DelegatedRevocationRequest,
IEAS,
MultiAttestationRequest,
MultiDelegatedAttestationRequest,
MultiDelegatedRevocationRequest,
MultiRevocationRequest,
RevocationRequest,
RevocationRequestData
} from "src/EAS/IEAS.sol";
import { ISchemaRegistry, SchemaRecord } from "src/EAS/ISchemaRegistry.sol";
struct AttestationsResult {
uint256 usedValue; // Total ETH amount that was sent to resolvers.
bytes32[] uids; // UIDs of the new attestations.
}
/// @custom:proxied true
/// @custom:predeploy 0x4200000000000000000000000000000000000021
/// @title EAS
/// @notice The Ethereum Attestation Service protocol.
contract EAS is IEAS, ISemver, EIP1271Verifier {
using Address for address payable;
error AlreadyRevoked();
error AlreadyRevokedOffchain();
error AlreadyTimestamped();
error InsufficientValue();
error InvalidAttestation();
error InvalidAttestations();
error InvalidExpirationTime();
error InvalidOffset();
error InvalidRegistry();
error InvalidRevocation();
error InvalidRevocations();
error InvalidSchema();
error InvalidVerifier();
error Irrevocable();
error NotPayable();
error WrongSchema();
// The global schema registry.
ISchemaRegistry private constant _schemaRegistry = ISchemaRegistry(Predeploys.SCHEMA_REGISTRY);
// The global mapping between attestations and their UIDs.
mapping(bytes32 uid => Attestation attestation) private _db;
// The global mapping between data and their timestamps.
mapping(bytes32 data => uint64 timestamp) private _timestamps;
// The global mapping between data and their revocation timestamps.
mapping(address revoker => mapping(bytes32 data => uint64 timestamp)) private _revocationsOffchain;
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 3] private __gap;
/// @notice Semantic version.
/// @custom:semver 1.4.1-beta.1
string public constant version = "1.4.1-beta.1";
/// @dev Creates a new EAS instance.
constructor() EIP1271Verifier("EAS", "1.3.0") { }
/// @inheritdoc IEAS
function getSchemaRegistry() external pure returns (ISchemaRegistry) {
return _schemaRegistry;
}
/// @inheritdoc IEAS
function attest(AttestationRequest calldata request) external payable returns (bytes32) {
AttestationRequestData[] memory data = new AttestationRequestData[](1);
data[0] = request.data;
return _attest(request.schema, data, msg.sender, msg.value, true).uids[0];
}
/// @inheritdoc IEAS
function attestByDelegation(DelegatedAttestationRequest calldata delegatedRequest)
external
payable
returns (bytes32)
{
_verifyAttest(delegatedRequest);
AttestationRequestData[] memory data = new AttestationRequestData[](1);
data[0] = delegatedRequest.data;
return _attest(delegatedRequest.schema, data, delegatedRequest.attester, msg.value, true).uids[0];
}
/// @inheritdoc IEAS
function multiAttest(MultiAttestationRequest[] calldata multiRequests)
external
payable
returns (bytes32[] memory)
{
// Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect
// all the returned UIDs into a single list.
uint256 length = multiRequests.length;
bytes32[][] memory totalUids = new bytes32[][](length);
uint256 totalUidsCount = 0;
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 availableValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == length - 1;
}
// Process the current batch of attestations.
MultiAttestationRequest calldata multiRequest = multiRequests[i];
// Ensure that data isn't empty.
if (multiRequest.data.length == 0) {
revert InvalidLength();
}
AttestationsResult memory res =
_attest(multiRequest.schema, multiRequest.data, msg.sender, availableValue, last);
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= res.usedValue;
// Collect UIDs (and merge them later).
totalUids[i] = res.uids;
unchecked {
totalUidsCount += res.uids.length;
}
}
// Merge all the collected UIDs and return them as a flatten array.
return _mergeUIDs(totalUids, totalUidsCount);
}
/// @inheritdoc IEAS
function multiAttestByDelegation(MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests)
external
payable
returns (bytes32[] memory)
{
// Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect
// all the returned UIDs into a single list.
uint256 length = multiDelegatedRequests.length;
bytes32[][] memory totalUids = new bytes32[][](length);
uint256 totalUidsCount = 0;
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 availableValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == length - 1;
}
MultiDelegatedAttestationRequest calldata multiDelegatedRequest = multiDelegatedRequests[i];
AttestationRequestData[] calldata data = multiDelegatedRequest.data;
// Ensure that no inputs are missing.
uint256 dataLength = data.length;
if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) {
revert InvalidLength();
}
// Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces.
for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) {
_verifyAttest(
DelegatedAttestationRequest({
schema: multiDelegatedRequest.schema,
data: data[j],
signature: multiDelegatedRequest.signatures[j],
attester: multiDelegatedRequest.attester,
deadline: multiDelegatedRequest.deadline
})
);
}
// Process the current batch of attestations.
AttestationsResult memory res =
_attest(multiDelegatedRequest.schema, data, multiDelegatedRequest.attester, availableValue, last);
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= res.usedValue;
// Collect UIDs (and merge them later).
totalUids[i] = res.uids;
unchecked {
totalUidsCount += res.uids.length;
}
}
// Merge all the collected UIDs and return them as a flatten array.
return _mergeUIDs(totalUids, totalUidsCount);
}
/// @inheritdoc IEAS
function revoke(RevocationRequest calldata request) external payable {
RevocationRequestData[] memory data = new RevocationRequestData[](1);
data[0] = request.data;
_revoke(request.schema, data, msg.sender, msg.value, true);
}
/// @inheritdoc IEAS
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable {
_verifyRevoke(delegatedRequest);
RevocationRequestData[] memory data = new RevocationRequestData[](1);
data[0] = delegatedRequest.data;
_revoke(delegatedRequest.schema, data, delegatedRequest.revoker, msg.value, true);
}
/// @inheritdoc IEAS
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable {
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 availableValue = msg.value;
uint256 length = multiRequests.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == length - 1;
}
MultiRevocationRequest calldata multiRequest = multiRequests[i];
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= _revoke(multiRequest.schema, multiRequest.data, msg.sender, availableValue, last);
}
}
/// @inheritdoc IEAS
function multiRevokeByDelegation(MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests)
external
payable
{
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 availableValue = msg.value;
uint256 length = multiDelegatedRequests.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == length - 1;
}
MultiDelegatedRevocationRequest memory multiDelegatedRequest = multiDelegatedRequests[i];
RevocationRequestData[] memory data = multiDelegatedRequest.data;
// Ensure that no inputs are missing.
uint256 dataLength = data.length;
if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) {
revert InvalidLength();
}
// Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces.
for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) {
_verifyRevoke(
DelegatedRevocationRequest({
schema: multiDelegatedRequest.schema,
data: data[j],
signature: multiDelegatedRequest.signatures[j],
revoker: multiDelegatedRequest.revoker,
deadline: multiDelegatedRequest.deadline
})
);
}
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -=
_revoke(multiDelegatedRequest.schema, data, multiDelegatedRequest.revoker, availableValue, last);
}
}
/// @inheritdoc IEAS
function timestamp(bytes32 data) external returns (uint64) {
uint64 time = _time();
_timestamp(data, time);
return time;
}
/// @inheritdoc IEAS
function revokeOffchain(bytes32 data) external returns (uint64) {
uint64 time = _time();
_revokeOffchain(msg.sender, data, time);
return time;
}
/// @inheritdoc IEAS
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64) {
uint64 time = _time();
uint256 length = data.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
_revokeOffchain(msg.sender, data[i], time);
}
return time;
}
/// @inheritdoc IEAS
function multiTimestamp(bytes32[] calldata data) external returns (uint64) {
uint64 time = _time();
uint256 length = data.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
_timestamp(data[i], time);
}
return time;
}
/// @inheritdoc IEAS
function getAttestation(bytes32 uid) external view returns (Attestation memory) {
return _db[uid];
}
/// @inheritdoc IEAS
function isAttestationValid(bytes32 uid) public view returns (bool) {
return _db[uid].uid != EMPTY_UID;
}
/// @inheritdoc IEAS
function getTimestamp(bytes32 data) external view returns (uint64) {
return _timestamps[data];
}
/// @inheritdoc IEAS
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64) {
return _revocationsOffchain[revoker][data];
}
/// @dev Attests to a specific schema.
/// @param schemaUID The unique identifier of the schema to attest to.
/// @param data The arguments of the attestation requests.
/// @param attester The attesting account.
/// @param availableValue The total available ETH amount that can be sent to the resolver.
/// @param last Whether this is the last attestations/revocations set.
/// @return The UID of the new attestations and the total sent ETH amount.
function _attest(
bytes32 schemaUID,
AttestationRequestData[] memory data,
address attester,
uint256 availableValue,
bool last
)
private
returns (AttestationsResult memory)
{
uint256 length = data.length;
AttestationsResult memory res;
res.uids = new bytes32[](length);
// Ensure that we aren't attempting to attest to a non-existing schema.
SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schemaUID);
if (schemaRecord.uid == EMPTY_UID) {
revert InvalidSchema();
}
Attestation[] memory attestations = new Attestation[](length);
uint256[] memory values = new uint256[](length);
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
AttestationRequestData memory request = data[i];
// Ensure that either no expiration time was set or that it was set in the future.
if (request.expirationTime != NO_EXPIRATION_TIME && request.expirationTime <= _time()) {
revert InvalidExpirationTime();
}
// Ensure that we aren't trying to make a revocable attestation for a non-revocable schema.
if (!schemaRecord.revocable && request.revocable) {
revert Irrevocable();
}
Attestation memory attestation = Attestation({
uid: EMPTY_UID,
schema: schemaUID,
refUID: request.refUID,
time: _time(),
expirationTime: request.expirationTime,
revocationTime: 0,
recipient: request.recipient,
attester: attester,
revocable: request.revocable,
data: request.data
});
// Look for the first non-existing UID (and use a bump seed/nonce in the rare case of a conflict).
bytes32 uid;
uint32 bump = 0;
while (true) {
uid = _getUID(attestation, bump);
if (_db[uid].uid == EMPTY_UID) {
break;
}
unchecked {
++bump;
}
}
attestation.uid = uid;
_db[uid] = attestation;
if (request.refUID != EMPTY_UID) {
// Ensure that we aren't trying to attest to a non-existing referenced UID.
if (!isAttestationValid(request.refUID)) {
revert NotFound();
}
}
attestations[i] = attestation;
values[i] = request.value;
res.uids[i] = uid;
emit Attested(request.recipient, attester, uid, schemaUID);
}
res.usedValue = _resolveAttestations(schemaRecord, attestations, values, false, availableValue, last);
return res;
}
/// @dev Revokes an existing attestation to a specific schema.
/// @param schemaUID The unique identifier of the schema to attest to.
/// @param data The arguments of the revocation requests.
/// @param revoker The revoking account.
/// @param availableValue The total available ETH amount that can be sent to the resolver.
/// @param last Whether this is the last attestations/revocations set.
/// @return Returns the total sent ETH amount.
function _revoke(
bytes32 schemaUID,
RevocationRequestData[] memory data,
address revoker,
uint256 availableValue,
bool last
)
private
returns (uint256)
{
// Ensure that a non-existing schema ID wasn't passed by accident.
SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schemaUID);
if (schemaRecord.uid == EMPTY_UID) {
revert InvalidSchema();
}
uint256 length = data.length;
Attestation[] memory attestations = new Attestation[](length);
uint256[] memory values = new uint256[](length);
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
RevocationRequestData memory request = data[i];
Attestation storage attestation = _db[request.uid];
// Ensure that we aren't attempting to revoke a non-existing attestation.
if (attestation.uid == EMPTY_UID) {
revert NotFound();
}
// Ensure that a wrong schema ID wasn't passed by accident.
if (attestation.schema != schemaUID) {
revert InvalidSchema();
}
// Allow only original attesters to revoke their attestations.
if (attestation.attester != revoker) {
revert AccessDenied();
}
// Please note that also checking of the schema itself is revocable is unnecessary, since it's not possible
// to
// make revocable attestations to an irrevocable schema.
if (!attestation.revocable) {
revert Irrevocable();
}
// Ensure that we aren't trying to revoke the same attestation twice.
if (attestation.revocationTime != 0) {
revert AlreadyRevoked();
}
attestation.revocationTime = _time();
attestations[i] = attestation;
values[i] = request.value;
emit Revoked(attestations[i].recipient, revoker, request.uid, schemaUID);
}
return _resolveAttestations(schemaRecord, attestations, values, true, availableValue, last);
}
/// @dev Resolves a new attestation or a revocation of an existing attestation.
/// @param schemaRecord The schema of the attestation.
/// @param attestation The data of the attestation to make/revoke.
/// @param value An explicit ETH amount to send to the resolver.
/// @param isRevocation Whether to resolve an attestation or its revocation.
/// @param availableValue The total available ETH amount that can be sent to the resolver.
/// @param last Whether this is the last attestations/revocations set.
/// @return Returns the total sent ETH amount.
function _resolveAttestation(
SchemaRecord memory schemaRecord,
Attestation memory attestation,
uint256 value,
bool isRevocation,
uint256 availableValue,
bool last
)
private
returns (uint256)
{
ISchemaResolver resolver = schemaRecord.resolver;
if (address(resolver) == address(0)) {
// Ensure that we don't accept payments if there is no resolver.
if (value != 0) {
revert NotPayable();
}
if (last) {
_refund(availableValue);
}
return 0;
}
// Ensure that we don't accept payments which can't be forwarded to the resolver.
if (value != 0) {
if (!resolver.isPayable()) {
revert NotPayable();
}
// Ensure that the attester/revoker doesn't try to spend more than available.
if (value > availableValue) {
revert InsufficientValue();
}
// Ensure to deduct the sent value explicitly.
unchecked {
availableValue -= value;
}
}
if (isRevocation) {
if (!resolver.revoke{ value: value }(attestation)) {
revert InvalidRevocation();
}
} else if (!resolver.attest{ value: value }(attestation)) {
revert InvalidAttestation();
}
if (last) {
_refund(availableValue);
}
return value;
}
/// @dev Resolves multiple attestations or revocations of existing attestations.
/// @param schemaRecord The schema of the attestation.
/// @param attestations The data of the attestations to make/revoke.
/// @param values Explicit ETH amounts to send to the resolver.
/// @param isRevocation Whether to resolve an attestation or its revocation.
/// @param availableValue The total available ETH amount that can be sent to the resolver.
/// @param last Whether this is the last attestations/revocations set.
/// @return Returns the total sent ETH amount.
function _resolveAttestations(
SchemaRecord memory schemaRecord,
Attestation[] memory attestations,
uint256[] memory values,
bool isRevocation,
uint256 availableValue,
bool last
)
private
returns (uint256)
{
uint256 length = attestations.length;
if (length == 1) {
return _resolveAttestation(schemaRecord, attestations[0], values[0], isRevocation, availableValue, last);
}
ISchemaResolver resolver = schemaRecord.resolver;
if (address(resolver) == address(0)) {
// Ensure that we don't accept payments if there is no resolver.
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
if (values[i] != 0) {
revert NotPayable();
}
}
if (last) {
_refund(availableValue);
}
return 0;
}
uint256 totalUsedValue = 0;
bool isResolverPayable = resolver.isPayable();
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
uint256 value = values[i];
// Ensure that we don't accept payments which can't be forwarded to the resolver.
if (value == 0) {
continue;
}
if (!isResolverPayable) {
revert NotPayable();
}
// Ensure that the attester/revoker doesn't try to spend more than available.
if (value > availableValue) {
revert InsufficientValue();
}
// Ensure to deduct the sent value explicitly and add it to the total used value by the batch.
unchecked {
availableValue -= value;
totalUsedValue += value;
}
}
if (isRevocation) {
if (!resolver.multiRevoke{ value: totalUsedValue }(attestations, values)) {
revert InvalidRevocations();
}
} else if (!resolver.multiAttest{ value: totalUsedValue }(attestations, values)) {
revert InvalidAttestations();
}
if (last) {
_refund(availableValue);
}
return totalUsedValue;
}
/// @dev Calculates a UID for a given attestation.
/// @param attestation The input attestation.
/// @param bump A bump value to use in case of a UID conflict.
/// @return Attestation UID.
function _getUID(Attestation memory attestation, uint32 bump) private pure returns (bytes32) {
return keccak256(
abi.encodePacked(
attestation.schema,
attestation.recipient,
attestation.attester,
attestation.time,
attestation.expirationTime,
attestation.revocable,
attestation.refUID,
attestation.data,
bump
)
);
}
/// @dev Refunds remaining ETH amount to the attester.
/// @param remainingValue The remaining ETH amount that was not sent to the resolver.
function _refund(uint256 remainingValue) private {
if (remainingValue > 0) {
// Using a regular transfer here might revert, for some non-EOA attesters, due to exceeding of the 2300
// gas limit which is why we're using call instead (via sendValue), which the 2300 gas limit does not
// apply for.
payable(msg.sender).sendValue(remainingValue);
}
}
/// @dev Timestamps the specified bytes32 data.
/// @param data The data to timestamp.
/// @param time The timestamp.
function _timestamp(bytes32 data, uint64 time) private {
if (_timestamps[data] != 0) {
revert AlreadyTimestamped();
}
_timestamps[data] = time;
emit Timestamped(data, time);
}
/// @dev Revokes the specified bytes32 data.
/// @param revoker The revoking account.
/// @param data The data to revoke.
/// @param time The timestamp the data was revoked with.
function _revokeOffchain(address revoker, bytes32 data, uint64 time) private {
mapping(bytes32 data => uint64 timestamp) storage revocations = _revocationsOffchain[revoker];
if (revocations[data] != 0) {
revert AlreadyRevokedOffchain();
}
revocations[data] = time;
emit RevokedOffchain(revoker, data, time);
}
/// @dev Merges lists of UIDs.
/// @param uidLists The provided lists of UIDs.
/// @param uidsCount Total UIDs count.
/// @return A merged and flatten list of all the UIDs.
function _mergeUIDs(bytes32[][] memory uidLists, uint256 uidsCount) private pure returns (bytes32[] memory) {
bytes32[] memory uids = new bytes32[](uidsCount);
uint256 currentIndex = 0;
uint256 uidListLength = uidLists.length;
for (uint256 i = 0; i < uidListLength; i = uncheckedInc(i)) {
bytes32[] memory currentUids = uidLists[i];
uint256 currentUidsLength = currentUids.length;
for (uint256 j = 0; j < currentUidsLength; j = uncheckedInc(j)) {
uids[currentIndex] = currentUids[j];
unchecked {
++currentIndex;
}
}
}
return uids;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ? {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
import "../Address.sol";
import "../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
* Argent and Gnosis Safe.
*
* _Available since v4.1._
*/
library SignatureChecker {
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
if (error == ECDSA.RecoverError.NoError && recovered == signer) {
return true;
}
(bool success, bytes memory result) = signer.staticcall(
abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
);
return (success &&
result.length == 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// A representation of an empty/uninitialized UID.
bytes32 constant EMPTY_UID = 0;
// A zero expiration represents an non-expiring attestation.
uint64 constant NO_EXPIRATION_TIME = 0;
error AccessDenied();
error DeadlineExpired();
error InvalidEAS();
error InvalidLength();
error InvalidSignature();
error NotFound();
/// @dev A struct representing ECDSA signature data.
struct Signature {
uint8 v; // The recovery ID.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 s; // The signature data.
}
/// @dev A struct representing a single attestation.
struct Attestation {
bytes32 uid; // A unique identifier of the attestation.
bytes32 schema; // The unique identifier of the schema.
uint64 time; // The time when the attestation was created (Unix timestamp).
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
uint64 revocationTime; // The time when the attestation was revoked (Unix timestamp).
bytes32 refUID; // The UID of the related attestation.
address recipient; // The recipient of the attestation.
address attester; // The attester/sender of the attestation.
bool revocable; // Whether the attestation is revocable.
bytes data; // Custom attestation data.
}
// Maximum upgrade forward-compatibility storage gap.
uint32 constant MAX_GAP = 50;
/// @dev A helper function to work with unchecked iterators in loops.
/// @param i The index to increment.
/// @return j The incremented index.
function uncheckedInc(uint256 i) pure returns (uint256 j) {
unchecked {
j = i + 1;
}
}
/// @dev A helper function that converts a string to a bytes32.
/// @param str The string to convert.
/// @return The converted bytes32.
function stringToBytes32(string memory str) pure returns (bytes32) {
bytes32 result;
assembly {
result := mload(add(str, 32))
}
return result;
}
/// @dev A helper function that converts a bytes32 to a string.
/// @param data The bytes32 data to convert.
/// @return The converted string.
function bytes32ToString(bytes32 data) pure returns (string memory) {
bytes memory byteArray = new bytes(32);
uint256 length = 0;
for (uint256 i = 0; i < 32; i = uncheckedInc(i)) {
bytes1 char = data[i];
if (char == 0x00) {
break;
}
byteArray[length] = char;
length = uncheckedInc(length);
}
bytes memory terminatedBytes = new bytes(length);
for (uint256 j = 0; j < length; j = uncheckedInc(j)) {
terminatedBytes[j] = byteArray[j];
}
return string(terminatedBytes);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "src/EAS/ISchemaRegistry.sol";
import { Attestation, Signature } from "src/EAS/Common.sol";
/// @dev A struct representing the arguments of the attestation request.
struct AttestationRequestData {
address recipient; // The recipient of the attestation.
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
bool revocable; // Whether the attestation is revocable.
bytes32 refUID; // The UID of the related attestation.
bytes data; // Custom attestation data.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user
// errors.
}
/// @dev A struct representing the full arguments of the attestation request.
struct AttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
}
/// @dev A struct representing the full arguments of the full delegated attestation request.
struct DelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
Signature signature; // The ECDSA signature data.
address attester; // The attesting account.
uint64 deadline; // The deadline of the signature/request.
}
/// @dev A struct representing the full arguments of the multi attestation request.
struct MultiAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation request.
}
/// @dev A struct representing the full arguments of the delegated multi attestation request.
struct MultiDelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation requests.
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with
// increasing nonces.
address attester; // The attesting account.
uint64 deadline; // The deadline of the signature/request.
}
/// @dev A struct representing the arguments of the revocation request.
struct RevocationRequestData {
bytes32 uid; // The UID of the attestation to revoke.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user
// errors.
}
/// @dev A struct representing the full arguments of the revocation request.
struct RevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
}
/// @dev A struct representing the arguments of the full delegated revocation request.
struct DelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
Signature signature; // The ECDSA signature data.
address revoker; // The revoking account.
uint64 deadline; // The deadline of the signature/request.
}
/// @dev A struct representing the full arguments of the multi revocation request.
struct MultiRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation request.
}
/// @dev A struct representing the full arguments of the delegated multi revocation request.
struct MultiDelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation requests.
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with
// increasing nonces.
address revoker; // The revoking account.
uint64 deadline; // The deadline of the signature/request.
}
/// @title IEAS
/// @notice The Ethereum Attestation Service interface.
interface IEAS {
/// @dev Emitted when an attestation has been made.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param uid The UID the revoked attestation.
/// @param schemaUID The UID of the schema.
event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);
/// @dev Emitted when an attestation has been revoked.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param schemaUID The UID of the schema.
/// @param uid The UID the revoked attestation.
event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);
/// @dev Emitted when a data has been timestamped.
/// @param data The data.
/// @param timestamp The timestamp.
event Timestamped(bytes32 indexed data, uint64 indexed timestamp);
/// @dev Emitted when a data has been revoked.
/// @param revoker The address of the revoker.
/// @param data The data.
/// @param timestamp The timestamp.
event RevokedOffchain(address indexed revoker, bytes32 indexed data, uint64 indexed timestamp);
/// @notice Returns the address of the global schema registry.
/// @return The address of the global schema registry.
function getSchemaRegistry() external view returns (ISchemaRegistry);
/// @notice Attests to a specific schema.
///
/// Example:
///
/// attest({
/// schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
/// data: {
/// recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
/// expirationTime: 0,
/// revocable: true,
/// refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
/// data: "0xF00D",
/// value: 0
/// }
/// })
///
/// @param request The arguments of the attestation request.
/// @return The UID of the new attestation.
function attest(AttestationRequest calldata request) external payable returns (bytes32);
/// @notice Attests to a specific schema via the provided EIP712 signature.
///
/// Example:
///
/// attestByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// signature: {
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e',
/// deadline: 1673891048
/// })
///
/// @param delegatedRequest The arguments of the delegated attestation request.
/// @return The UID of the new attestation.
function attestByDelegation(DelegatedAttestationRequest calldata delegatedRequest)
external
payable
returns (bytes32);
/// @notice Attests to multiple schemas.
///
/// Example:
///
/// multiAttest([{
/// schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 1000
/// },
/// {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174',
/// data: '0x00',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: true,
/// refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f',
/// data: '0x12345678',
/// value: 0
/// },
/// }])
///
/// @param multiRequests The arguments of the multi attestation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
function multiAttest(MultiAttestationRequest[] calldata multiRequests)
external
payable
returns (bytes32[] memory);
/// @notice Attests to multiple schemas using via provided EIP712 signatures.
///
/// Example:
///
/// multiAttestByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// {
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x00',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4',
/// deadline: 1673891048
/// }])
///
/// @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be
/// grouped by distinct schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
function multiAttestByDelegation(MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests)
external
payable
returns (bytes32[] memory);
/// @notice Revokes an existing attestation to a specific schema.
///
/// Example:
///
/// revoke({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
/// value: 0
/// }
/// })
///
/// @param request The arguments of the revocation request.
function revoke(RevocationRequest calldata request) external payable;
/// @notice Revokes an existing attestation to a specific schema via the provided EIP712 signature.
///
/// Example:
///
/// revokeByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
/// value: 0
/// },
/// signature: {
/// v: 27,
/// r: '0xb593...7142',
/// s: '0x0f5b...2cce'
/// },
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
/// deadline: 1673891048
/// })
///
/// @param delegatedRequest The arguments of the delegated revocation request.
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;
/// @notice Revokes existing attestations to multiple schemas.
///
/// Example:
///
/// multiRevoke([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
/// value: 0
/// },
/// }])
///
/// @param multiRequests The arguments of the multi revocation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;
/// @notice Revokes existing attestations to multiple schemas via provided EIP712 signatures.
///
/// Example:
///
/// multiRevokeByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
/// deadline: 1673891048
/// }])
///
/// @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests
/// should be
/// grouped by distinct schema ids to benefit from the best batching optimization.
function multiRevokeByDelegation(MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests)
external
payable;
/// @notice Timestamps the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function timestamp(bytes32 data) external returns (uint64);
/// @notice Timestamps the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function multiTimestamp(bytes32[] calldata data) external returns (uint64);
/// @notice Revokes the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function revokeOffchain(bytes32 data) external returns (uint64);
/// @notice Revokes the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64);
/// @notice Returns an existing attestation by UID.
/// @param uid The UID of the attestation to retrieve.
/// @return The attestation data members.
function getAttestation(bytes32 uid) external view returns (Attestation memory);
/// @notice Checks whether an attestation exists.
/// @param uid The UID of the attestation to retrieve.
/// @return Whether an attestation exists.
function isAttestationValid(bytes32 uid) external view returns (bool);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getTimestamp(bytes32 data) external view returns (uint64);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaResolver } from "src/EAS/resolver/ISchemaResolver.sol";
/// @title A struct representing a record for a submitted schema.
struct SchemaRecord {
bytes32 uid; // The unique identifier of the schema.
ISchemaResolver resolver; // Optional schema resolver.
bool revocable; // Whether the schema allows revocations explicitly.
string schema; // Custom specification of the schema (e.g., an ABI).
}
/// @title ISchemaRegistry
/// @notice The interface of global attestation schemas for the Ethereum Attestation Service protocol.
interface ISchemaRegistry {
/// @dev Emitted when a new schema has been registered
/// @param uid The schema UID.
/// @param registerer The address of the account used to register the schema.
/// @param schema The schema data.
event Registered(bytes32 indexed uid, address indexed registerer, SchemaRecord schema);
/// @dev Submits and reserves a new schema
/// @param schema The schema data schema.
/// @param resolver An optional schema resolver.
/// @param revocable Whether the schema allows revocations explicitly.
/// @return The UID of the new schema.
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32);
/// @dev Returns an existing schema by UID
/// @param uid The UID of the schema to retrieve.
/// @return The schema data members.
function getSchema(bytes32 uid) external view returns (SchemaRecord memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import {
AttestationRequestData,
DelegatedAttestationRequest,
DelegatedRevocationRequest,
RevocationRequestData
} from "src/EAS/IEAS.sol";
import {
DeadlineExpired,
NO_EXPIRATION_TIME,
Signature,
InvalidSignature,
MAX_GAP,
stringToBytes32,
bytes32ToString
} from "src/EAS/Common.sol";
/// @title EIP1271Verifier
/// @notice EIP1271Verifier typed signatures verifier for EAS delegated attestations.
abstract contract EIP1271Verifier is EIP712 {
using Address for address;
error InvalidNonce();
// The hash of the data type used to relay calls to the attest function. It's the value of
// keccak256("Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32
// refUID,bytes data,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant ATTEST_TYPEHASH = 0xfeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d988076;
// The hash of the data type used to relay calls to the revoke function. It's the value of
// keccak256("Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant REVOKE_TYPEHASH = 0xb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e75;
// The user readable name of the signing domain.
bytes32 private immutable _name;
// Replay protection nonces.
mapping(address => uint256) private _nonces;
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 1] private __gap;
/// @dev Emitted when users invalidate nonces by increasing their nonces to (higher) new values.
/// @param oldNonce The previous nonce.
/// @param newNonce The new value.
event NonceIncreased(uint256 oldNonce, uint256 newNonce);
/// @dev Creates a new EIP1271Verifier instance.
/// @param version The current major version of the signing domain
constructor(string memory name, string memory version) EIP712(name, version) {
_name = stringToBytes32(name);
}
/// @notice Returns the domain separator used in the encoding of the signatures for attest, and revoke.
/// @return The domain separator used in the encoding of the signatures for attest, and revoke.
function getDomainSeparator() external view returns (bytes32) {
return _domainSeparatorV4();
}
/// @notice Returns the current nonce per-account.
/// @param account The requested account.
/// @return The current nonce.
function getNonce(address account) external view returns (uint256) {
return _nonces[account];
}
/// @notice Returns the EIP712 type hash for the attest function.
/// @return The EIP712 type hash for the attest function.
function getAttestTypeHash() external pure returns (bytes32) {
return ATTEST_TYPEHASH;
}
/// @notice Returns the EIP712 type hash for the revoke function.
/// @return The EIP712 type hash for the revoke function.
function getRevokeTypeHash() external pure returns (bytes32) {
return REVOKE_TYPEHASH;
}
/// @notice Returns the EIP712 name.
/// @return The EIP712 name.
function getName() external view returns (string memory) {
return bytes32ToString(_name);
}
/// @notice Provides users an option to invalidate nonces by increasing their nonces to (higher) new values.
/// @param newNonce The (higher) new value.
function increaseNonce(uint256 newNonce) external {
uint256 oldNonce = _nonces[msg.sender];
if (newNonce <= oldNonce) {
revert InvalidNonce();
}
_nonces[msg.sender] = newNonce;
emit NonceIncreased({ oldNonce: oldNonce, newNonce: newNonce });
}
/// @notice Verifies delegated attestation request.
/// @param request The arguments of the delegated attestation request.
function _verifyAttest(DelegatedAttestationRequest memory request) internal {
if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) {
revert DeadlineExpired();
}
AttestationRequestData memory data = request.data;
Signature memory signature = request.signature;
bytes32 hash = _hashTypedDataV4(
keccak256(
abi.encode(
ATTEST_TYPEHASH,
request.attester,
request.schema,
data.recipient,
data.expirationTime,
data.revocable,
data.refUID,
keccak256(data.data),
data.value,
_nonces[request.attester]++,
request.deadline
)
)
);
if (
!SignatureChecker.isValidSignatureNow(
request.attester, hash, abi.encodePacked(signature.r, signature.s, signature.v)
)
) {
revert InvalidSignature();
}
}
/// @notice Verifies delegated revocation request.
/// @param request The arguments of the delegated revocation request.
function _verifyRevoke(DelegatedRevocationRequest memory request) internal {
if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) {
revert DeadlineExpired();
}
RevocationRequestData memory data = request.data;
Signature memory signature = request.signature;
bytes32 hash = _hashTypedDataV4(
keccak256(
abi.encode(
REVOKE_TYPEHASH,
request.revoker,
request.schema,
data.uid,
data.value,
_nonces[request.revoker]++,
request.deadline
)
)
);
if (
!SignatureChecker.isValidSignatureNow(
request.revoker, hash, abi.encodePacked(signature.r, signature.s, signature.v)
)
) {
revert InvalidSignature();
}
}
/// @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the
/// current block time.
function _time() internal view virtual returns (uint64) {
return uint64(block.timestamp);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Attestation } from "../Common.sol";
/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver {
/// @notice Checks if the resolver can be sent ETH.
/// @return Whether the resolver supports ETH transfers.
function isPayable() external pure returns (bool);
/// @notice Processes an attestation and verifies whether it's valid.
/// @param attestation The new attestation.
/// @return Whether the attestation is valid.
function attest(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes multiple attestations and verifies whether they are valid.
/// @param attestations The new attestations.
/// @param values Explicit ETH amounts which were sent with each attestation.
/// @return Whether all the attestations are valid.
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
)
external
payable
returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @return Whether the attestation can be revoked.
function revoke(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes revocation of multiple attestation and verifies they can be revoked.
/// @param attestations The existing attestations to be revoked.
/// @param values Explicit ETH amounts which were sent with each revocation.
/// @return Whether the attestations can be revoked.
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
)
external
payable
returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Predeploys
/// @notice Contains constant addresses for protocol contracts that are pre-deployed to the L2 system.
// This excludes the preinstalls (non-protocol contracts).
library Predeploys {
/// @notice Number of predeploy-namespace addresses reserved for protocol usage.
uint256 internal constant PREDEPLOY_COUNT = 2048;
/// @custom:legacy
/// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated
/// L2ToL1MessagePasser contract instead.
address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;
/// @custom:legacy
/// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger
/// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.
/// Not embedded into new OP-Stack chains.
address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;
/// @custom:legacy
/// @notice Address of the DeployerWhitelist predeploy. No longer active.
address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;
/// @notice Address of the canonical WETH contract.
address internal constant WETH = 0x4200000000000000000000000000000000000006;
/// @notice Address of the L2CrossDomainMessenger predeploy.
address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007;
/// @notice Address of the GasPriceOracle predeploy. Includes fee information
/// and helpers for computing the L1 portion of the transaction fee.
address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;
/// @notice Address of the L2StandardBridge predeploy.
address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;
//// @notice Address of the SequencerFeeWallet predeploy.
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
/// @notice Address of the OptimismMintableERC20Factory predeploy.
address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012;
/// @custom:legacy
/// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy
/// instead, which exposes more information about the L1 state.
address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;
/// @notice Address of the L2ERC721Bridge predeploy.
address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;
/// @notice Address of the L1Block predeploy.
address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;
/// @notice Address of the L2ToL1MessagePasser predeploy.
address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;
/// @notice Address of the OptimismMintableERC721Factory predeploy.
address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017;
/// @notice Address of the ProxyAdmin predeploy.
address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;
/// @notice Address of the BaseFeeVault predeploy.
address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;
/// @notice Address of the L1FeeVault predeploy.
address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;
/// @notice Address of the SchemaRegistry predeploy.
address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020;
/// @notice Address of the EAS predeploy.
address internal constant EAS = 0x4200000000000000000000000000000000000021;
/// @notice Address of the GovernanceToken predeploy.
address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;
/// @custom:legacy
/// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the
/// state trie as of the Bedrock upgrade. Contract has been locked and write functions
/// can no longer be accessed.
address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;
/// @notice Address of the CrossL2Inbox predeploy.
address internal constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022;
/// @notice Address of the L2ToL2CrossDomainMessenger predeploy.
address internal constant L2_TO_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000023;
/// @notice Address of the SuperchainWETH predeploy.
address internal constant SUPERCHAIN_WETH = 0x4200000000000000000000000000000000000024;
/// @notice Address of the ETHLiquidity predeploy.
address internal constant ETH_LIQUIDITY = 0x4200000000000000000000000000000000000025;
/// TODO: Add correct predeploy address for OptimismSuperchainERC20Factory
/// @notice Address of the OptimismSuperchainERC20Factory predeploy.
address internal constant OPTIMISM_SUPERCHAIN_ERC20_FACTORY = 0x4200000000000000000000000000000000000026;
/// @notice Returns the name of the predeploy at the given address.
function getName(address _addr) internal pure returns (string memory out_) {
require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy");
if (_addr == LEGACY_MESSAGE_PASSER) return "LegacyMessagePasser";
if (_addr == L1_MESSAGE_SENDER) return "L1MessageSender";
if (_addr == DEPLOYER_WHITELIST) return "DeployerWhitelist";
if (_addr == WETH) return "WETH";
if (_addr == L2_CROSS_DOMAIN_MESSENGER) return "L2CrossDomainMessenger";
if (_addr == GAS_PRICE_ORACLE) return "GasPriceOracle";
if (_addr == L2_STANDARD_BRIDGE) return "L2StandardBridge";
if (_addr == SEQUENCER_FEE_WALLET) return "SequencerFeeVault";
if (_addr == OPTIMISM_MINTABLE_ERC20_FACTORY) return "OptimismMintableERC20Factory";
if (_addr == L1_BLOCK_NUMBER) return "L1BlockNumber";
if (_addr == L2_ERC721_BRIDGE) return "L2ERC721Bridge";
if (_addr == L1_BLOCK_ATTRIBUTES) return "L1Block";
if (_addr == L2_TO_L1_MESSAGE_PASSER) return "L2ToL1MessagePasser";
if (_addr == OPTIMISM_MINTABLE_ERC721_FACTORY) return "OptimismMintableERC721Factory";
if (_addr == PROXY_ADMIN) return "ProxyAdmin";
if (_addr == BASE_FEE_VAULT) return "BaseFeeVault";
if (_addr == L1_FEE_VAULT) return "L1FeeVault";
if (_addr == SCHEMA_REGISTRY) return "SchemaRegistry";
if (_addr == EAS) return "EAS";
if (_addr == GOVERNANCE_TOKEN) return "GovernanceToken";
if (_addr == LEGACY_ERC20_ETH) return "LegacyERC20ETH";
if (_addr == CROSS_L2_INBOX) return "CrossL2Inbox";
if (_addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) return "L2ToL2CrossDomainMessenger";
if (_addr == SUPERCHAIN_WETH) return "SuperchainWETH";
if (_addr == ETH_LIQUIDITY) return "ETHLiquidity";
if (_addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) return "OptimismSuperchainERC20Factory";
revert("Predeploys: unnamed predeploy");
}
/// @notice Returns true if the predeploy is not proxied.
function notProxied(address _addr) internal pure returns (bool) {
return _addr == GOVERNANCE_TOKEN || _addr == WETH;
}
/// @notice Returns true if the address is a defined predeploy that is embedded into new OP-Stack chains.
function isSupportedPredeploy(address _addr, bool _useInterop) internal pure returns (bool) {
return _addr == LEGACY_MESSAGE_PASSER || _addr == DEPLOYER_WHITELIST || _addr == WETH
|| _addr == L2_CROSS_DOMAIN_MESSENGER || _addr == GAS_PRICE_ORACLE || _addr == L2_STANDARD_BRIDGE
|| _addr == SEQUENCER_FEE_WALLET || _addr == OPTIMISM_MINTABLE_ERC20_FACTORY || _addr == L1_BLOCK_NUMBER
|| _addr == L2_ERC721_BRIDGE || _addr == L1_BLOCK_ATTRIBUTES || _addr == L2_TO_L1_MESSAGE_PASSER
|| _addr == OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == PROXY_ADMIN || _addr == BASE_FEE_VAULT
|| _addr == L1_FEE_VAULT || _addr == SCHEMA_REGISTRY || _addr == EAS || _addr == GOVERNANCE_TOKEN
|| (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER)
|| (_useInterop && _addr == SUPERCHAIN_WETH) || (_useInterop && _addr == ETH_LIQUIDITY)
|| (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY);
}
function isPredeployNamespace(address _addr) internal pure returns (bool) {
return uint160(_addr) >> 11 == uint160(0x4200000000000000000000000000000000000000) >> 11;
}
/// @notice Function to compute the expected address of the predeploy implementation
/// in the genesis state.
function predeployToCodeNamespace(address _addr) internal pure returns (address) {
require(
isPredeployNamespace(_addr), "Predeploys: can only derive code-namespace address for predeploy addresses"
);
return address(
uint160(uint256(uint160(_addr)) & 0xffff | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000)))
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ISemver
/// @notice ISemver is a simple contract for ensuring that contracts are
/// versioned using semantic versioning.
interface ISemver {
/// @notice Getter for the semantic version of the contract. This is not
/// meant to be used onchain but instead meant to be used by offchain
/// tooling.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}{
"evmVersion": "paris",
"metadata": {
"appendCBOR": true,
"bytecodeHash": "none",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"remappings": [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-v5/=lib/openzeppelin-contracts-v5/contracts/",
"@rari-capital/solmate/=lib/solmate/",
"@lib-keccak/=lib/lib-keccak/contracts/lib/",
"@solady/=lib/solady/src/",
"forge-std/=lib/forge-std/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"safe-contracts/=lib/safe-contracts/contracts/",
"kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/",
"gelato/=lib/automate/contracts/",
"@solady-test/=lib/lib-keccak/lib/solady/test/",
"automate/=lib/automate/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts-v5/lib/erc4626-tests/",
"hardhat/=lib/automate/node_modules/hardhat/",
"lib-keccak/=lib/lib-keccak/contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts-v5/=lib/openzeppelin-contracts-v5/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"prb-test/=lib/automate/lib/prb-test/src/",
"prb/-est/=lib/automate/lib/prb-test/src/",
"solady-v0.0.245/=lib/solady-v0.0.245/src/",
"solady/=lib/solady/",
"solmate/=lib/solmate/src/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"AlreadyRevoked","type":"error"},{"inputs":[],"name":"AlreadyRevokedOffchain","type":"error"},{"inputs":[],"name":"AlreadyTimestamped","type":"error"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"InvalidAttestation","type":"error"},{"inputs":[],"name":"InvalidAttestations","type":"error"},{"inputs":[],"name":"InvalidExpirationTime","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidOffset","type":"error"},{"inputs":[],"name":"InvalidRegistry","type":"error"},{"inputs":[],"name":"InvalidRevocation","type":"error"},{"inputs":[],"name":"InvalidRevocations","type":"error"},{"inputs":[],"name":"InvalidSchema","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidVerifier","type":"error"},{"inputs":[],"name":"Irrevocable","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[],"name":"NotPayable","type":"error"},{"inputs":[],"name":"WrongSchema","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"attester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"uid","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"schemaUID","type":"bytes32"}],"name":"Attested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newNonce","type":"uint256"}],"name":"NonceIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"attester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"uid","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"schemaUID","type":"bytes32"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"revoker","type":"address"},{"indexed":true,"internalType":"bytes32","name":"data","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"timestamp","type":"uint64"}],"name":"RevokedOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"data","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"timestamp","type":"uint64"}],"name":"Timestamped","type":"event"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData","name":"data","type":"tuple"}],"internalType":"struct AttestationRequest","name":"request","type":"tuple"}],"name":"attest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData","name":"data","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature","name":"signature","type":"tuple"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct DelegatedAttestationRequest","name":"delegatedRequest","type":"tuple"}],"name":"attestByDelegation","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAttestTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"uid","type":"bytes32"}],"name":"getAttestation","outputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"revoker","type":"address"},{"internalType":"bytes32","name":"data","type":"bytes32"}],"name":"getRevokeOffchain","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRevokeTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getSchemaRegistry","outputs":[{"internalType":"contract ISchemaRegistry","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"data","type":"bytes32"}],"name":"getTimestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"}],"name":"increaseNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"uid","type":"bytes32"}],"name":"isAttestationValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData[]","name":"data","type":"tuple[]"}],"internalType":"struct MultiAttestationRequest[]","name":"multiRequests","type":"tuple[]"}],"name":"multiAttest","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData[]","name":"data","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"signatures","type":"tuple[]"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct MultiDelegatedAttestationRequest[]","name":"multiDelegatedRequests","type":"tuple[]"}],"name":"multiAttestByDelegation","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData[]","name":"data","type":"tuple[]"}],"internalType":"struct MultiRevocationRequest[]","name":"multiRequests","type":"tuple[]"}],"name":"multiRevoke","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData[]","name":"data","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"signatures","type":"tuple[]"},{"internalType":"address","name":"revoker","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct MultiDelegatedRevocationRequest[]","name":"multiDelegatedRequests","type":"tuple[]"}],"name":"multiRevokeByDelegation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"multiRevokeOffchain","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"multiTimestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData","name":"data","type":"tuple"}],"internalType":"struct RevocationRequest","name":"request","type":"tuple"}],"name":"revoke","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData","name":"data","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature","name":"signature","type":"tuple"},{"internalType":"address","name":"revoker","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct DelegatedRevocationRequest","name":"delegatedRequest","type":"tuple"}],"name":"revokeByDelegation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"data","type":"bytes32"}],"name":"revokeOffchain","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"data","type":"bytes32"}],"name":"timestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040526004361061018b5760003560e01c806395411525116100d6578063d45c44351161007f578063ed24911d11610059578063ed24911d146104fd578063f10b5cc814610512578063f17325e71461054157600080fd5b8063d45c443514610467578063e30bb5631461049e578063e71ff365146104dd57600080fd5b8063b469318d116100b0578063b469318d146103ba578063b83010d314610414578063cf190f341461044757600080fd5b80639541152514610367578063a3112a641461037a578063a6d4dbc7146103a757600080fd5b806344adc90e116101385780634d003070116101125780634d003070146102de57806354fd4d50146102fe57806379f7573a1461034757600080fd5b806344adc90e1461029857806346926267146102b85780634cb7e9e5146102cb57600080fd5b806317d7de7c1161016957806317d7de7c146102205780632d0335ab146102425780633c0427151461028557600080fd5b80630eabf6601461019057806312b11a17146101a557806313893f61146101e7575b600080fd5b6101a361019e3660046134c8565b610554565b005b3480156101b157600080fd5b507ffeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d9880765b6040519081526020015b60405180910390f35b3480156101f357600080fd5b506102076102023660046134c8565b6106eb565b60405167ffffffffffffffff90911681526020016101de565b34801561022c57600080fd5b50610235610730565b6040516101de9190613578565b34801561024e57600080fd5b506101d461025d3660046135bd565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101d46102933660046135da565b610760565b6102ab6102a63660046134c8565b610863565b6040516101de9190613615565b6101a36102c6366004613659565b6109e4565b6101a36102d93660046134c8565b610a68565b3480156102ea57600080fd5b506102076102f9366004613671565b610b4b565b34801561030a57600080fd5b506102356040518060400160405280600c81526020017f312e342e312d626574612e31000000000000000000000000000000000000000081525081565b34801561035357600080fd5b506101a3610362366004613671565b610b58565b6102ab6103753660046134c8565b610bef565b34801561038657600080fd5b5061039a610395366004613671565b610e62565b6040516101de9190613771565b6101a36103b5366004613784565b611025565b3480156103c657600080fd5b506102076103d5366004613797565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561042057600080fd5b507fb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e756101d4565b34801561045357600080fd5b50610207610462366004613671565b6110ca565b34801561047357600080fd5b50610207610482366004613671565b60009081526033602052604090205467ffffffffffffffff1690565b3480156104aa57600080fd5b506104cd6104b9366004613671565b600090815260326020526040902054151590565b60405190151581526020016101de565b3480156104e957600080fd5b506102076104f83660046134c8565b6110d8565b34801561050957600080fd5b506101d4611110565b34801561051e57600080fd5b5060405173420000000000000000000000000000000000002081526020016101de565b6101d461054f3660046137c3565b61111a565b348160005b818110156106e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018114600086868481811061059a5761059a6137fe565b90506020028101906105ac919061382d565b6105b590613ac3565b60208101518051919250908015806105d257508260400151518114155b15610609576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106ad576106a56040518060a001604052808660000151815260200185848151811061063e5761063e6137fe565b6020026020010151815260200186604001518481518110610661576106616137fe565b60200260200101518152602001866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866080015167ffffffffffffffff168152506111d8565b60010161060c565b506106c383600001518385606001518a886113e9565b6106cd9088613bed565b9650505050506106dd8160010190565b9050610559565b5050505050565b60004282825b818110156107245761071c3387878481811061070f5761070f6137fe565b9050602002013585611a18565b6001016106f1565b50909150505b92915050565b606061075b7f4541530000000000000000000000000000000000000000000000000000000000611b17565b905090565b600061077361076e83613d22565b611ca5565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161078a5790505090506107f86020840184613d9d565b61080190613dd1565b81600081518110610814576108146137fe565b602090810291909101015261083d83358261083560c0870160a088016135bd565b346001611e2f565b60200151600081518110610853576108536137fe565b6020026020010151915050919050565b60608160008167ffffffffffffffff8111156108815761088161386b565b6040519080825280602002602001820160405280156108b457816020015b606081526020019060019003908161089f5790505b509050600034815b848110156109ce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85018114368989848181106108fc576108fc6137fe565b905060200281019061090e9190613ddd565b905061091d6020820182613e11565b9050600003610958576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061097d823561096c6020850185613e11565b61097591613e79565b338887611e2f565b805190915061098c9086613bed565b945080602001518785815181106109a5576109a56137fe565b6020026020010181905250806020015151860195505050506109c78160010190565b90506108bc565b506109d98383612541565b979650505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816109fb579050509050610a3636839003830160208401613eed565b81600081518110610a4957610a496137fe565b6020908102919091010152610a63823582333460016113e9565b505050565b348160005b818110156106e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201811436868684818110610aad57610aad6137fe565b9050602002810190610abf9190613ddd565b9050610b2c8135610ad36020840184613f09565b808060200260200160405190810160405280939291908181526020016000905b82821015610b1f57610b1060408302860136819003810190613eed565b81526020019060010190610af3565b50505050503388866113e9565b610b369086613bed565b94505050610b448160010190565b9050610a6d565b60004261072a838261262b565b33600090815260208190526040902054808211610ba1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152602081815260409182902084905581518381529081018490527f57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7910160405180910390a15050565b60608160008167ffffffffffffffff811115610c0d57610c0d61386b565b604051908082528060200260200182016040528015610c4057816020015b6060815260200190600190039081610c2b5790505b509050600034815b848110156109ce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501811436898984818110610c8857610c886137fe565b9050602002810190610c9a919061382d565b9050366000610cac6020840184613e11565b909250905080801580610ccd5750610cc76040850185613f71565b90508114155b15610d04576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610de557610ddd6040518060a0016040528087600001358152602001868685818110610d3957610d396137fe565b9050602002810190610d4b9190613d9d565b610d5490613dd1565b8152602001610d666040890189613f71565b85818110610d7657610d766137fe565b905060600201803603810190610d8c9190613fd8565b8152602001610da16080890160608a016135bd565b73ffffffffffffffffffffffffffffffffffffffff168152602001610dcc60a0890160808a01613ff4565b67ffffffffffffffff169052611ca5565b600101610d07565b506000610e0e8535610df78587613e79565b610e076080890160608a016135bd565b8b8a611e2f565b8051909150610e1d9089613bed565b975080602001518a8881518110610e3657610e366137fe565b602002602001018190525080602001515189019850505050505050610e5b8160010190565b9050610c48565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610f9c9061400f565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc89061400f565b80156110155780601f10610fea57610100808354040283529160200191611015565b820191906000526020600020905b815481529060010190602001808311610ff857829003601f168201915b5050505050815250509050919050565b61103c6110373683900383018361405c565b6111d8565b604080516001808252818301909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161105357905050905061108e36839003830160208401613eed565b816000815181106110a1576110a16137fe565b6020908102919091010152610a638235826110c260e0860160c087016135bd565b3460016113e9565b60004261072a338483611a18565b60004282825b81811015610724576111088686838181106110fb576110fb6137fe565b905060200201358461262b565b6001016110de565b600061075b6126ed565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816111345790505090506111a26020840184613d9d565b6111ab90613dd1565b816000815181106111be576111be6137fe565b602090810291909101015261083d83358233346001611e2f565b608081015167ffffffffffffffff161580159061120c57504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611243576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401516060850151855184518587015173ffffffffffffffffffffffffffffffffffffffff84166000908152978890529487208054969794969495611337957fb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e7595949392886112ba836140ca565b909155506080808c015160408051602081019990995273ffffffffffffffffffffffffffffffffffffffff9097169688019690965260608701949094529285019190915260a084015260c083015267ffffffffffffffff1660e0820152610100015b60405160208183030381529060405280519060200120612821565b90506113ad84606001518284602001518560400151866000015160405160200161139993929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604051602081830303815290604052612834565b6113e3576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611457573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261149d9190810190614102565b80519091506114d8576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff8111156114f5576114f561386b565b60405190808252806020026020018201604052801561159457816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115135790505b50905060008267ffffffffffffffff8111156115b2576115b261386b565b6040519080825280602002602001820160405280156115db578160200160208202803683370190505b50905060005b838110156119fa5760008a82815181106115fd576115fd6137fe565b6020908102919091018101518051600090815260329092526040909120805491925090611656576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611693576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c81169116146116e9576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff1661173f576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611799576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805483916101208401916118a59061400f565b80601f01602080910402602001604051908101604052809291908181526020018280546118d19061400f565b801561191e5780601f106118f35761010080835404028352916020019161191e565b820191906000526020600020905b81548152906001019060200180831161190157829003601f168201915b505050505081525050858481518110611939576119396137fe565b6020026020010181905250816020015184848151811061195b5761195b6137fe565b6020026020010181815250508c8b73ffffffffffffffffffffffffffffffffffffffff16868581518110611991576119916137fe565b602002602001015160c0015173ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f61585600001516040516119e891815260200190565b60405180910390a450506001016115e1565b50611a0a84838360018b8b612a03565b9a9950505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611a8c576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b6020811015611be2576000858260208110611b5d57611b5d6137fe565b1a60f81b90507fff000000000000000000000000000000000000000000000000000000000000008116600003611b935750611be2565b80848481518110611ba657611ba66137fe565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060019182019101611b40565b5060008167ffffffffffffffff811115611bfe57611bfe61386b565b6040519080825280601f01601f191660200182016040528015611c28576020820181803683370190505b50905060005b82811015611c9c57838181518110611c4857611c486137fe565b602001015160f81c60f81b828281518110611c6557611c656137fe565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611c2e565b50949350505050565b608081015167ffffffffffffffff1615801590611cd957504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611d10576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401516060808601518651855186880151868801519488015160808901518051908b012060a08a015173ffffffffffffffffffffffffffffffffffffffff871660009081529b8c9052988b2080549a9b989a9899611337997ffeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d988076999493928c611da0836140ca565b919050558e6080015160405160200161131c9b9a999897969594939291909a8b5273ffffffffffffffffffffffffffffffffffffffff998a1660208c015260408b019890985295909716606089015267ffffffffffffffff938416608089015291151560a088015260c087015260e0860152610100850193909352610120840152166101408201526101600190565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff811115611e7457611e7461386b565b604051908082528060200260200182016040528015611e9d578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611f0f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f559190810190614102565b8051909150611f90576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff811115611fab57611fab61386b565b60405190808252806020026020018201604052801561204a57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611fc95790505b50905060008467ffffffffffffffff8111156120685761206861386b565b604051908082528060200260200182016040528015612091578160200160208202803683370190505b50905060005b858110156125205760008b82815181106120b3576120b36137fe565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff16141580156120fe57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15612135576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151158015612148575080604001515b1561217f576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016121a34290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6122458382612df4565b600081815260326020526040902054909250156122645760010161223b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906123e49082614228565b50505060608401511561243b57606084015160009081526032602052604090205461243b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8287868151811061244e5761244e6137fe565b60200260200101819052508360a00151868681518110612470576124706137fe565b6020026020010181815250508189602001518681518110612493576124936137fe565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b358560405161250391815260200190565b60405180910390a4505050506125198160010190565b9050612097565b5061253083838360008c8c612a03565b845250919998505050505050505050565b606060008267ffffffffffffffff81111561255e5761255e61386b565b604051908082528060200260200182016040528015612587578160200160208202803683370190505b508451909150600090815b818110156126205760008782815181106125ae576125ae6137fe565b6020026020010151905060008151905060005b8181101561260c578281815181106125db576125db6137fe565b60200260200101518787815181106125f5576125f56137fe565b6020908102919091010152600195860195016125c1565b5050506126198160010190565b9050612592565b509195945050505050565b60008281526033602052604090205467ffffffffffffffff161561267b576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000009101223d33eeaea94045bb2920f00ba0f7a475bc1614801561275357507f00000000000000000000000000000000000000000000000000000000000b67d246145b1561277d57507ff8fb232858d8ad10fc42a30f144b1d6b4494961ffc5afd1f35cd47572228de0590565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f9fed719e0073f95229e6f4f6b6f28f260c524ab08aa40b11f9c28cb710d7c72a828401527f6a08c3e203132c561752255a4d52ffae85bb9c5d33cb3291520dea1b8435638960608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b600061072a61282e6126ed565b83612e53565b60008060006128438585612e95565b9092509050600081600481111561285c5761285c614342565b14801561289457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156128a4576001925050506129fc565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016128d9929190614371565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516129629190614392565b600060405180830381855afa9150503d806000811461299d576040519150601f19603f3d011682016040523d82523d6000602084013e6129a2565b606091505b50915091508180156129b5575080516020145b80156129f5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906129f390830160209081019084016143a4565b145b9450505050505b9392505050565b84516000906001819003612a5b57612a538888600081518110612a2857612a286137fe565b602002602001015188600081518110612a4357612a436137fe565b6020026020010151888888612eda565b915050612dea565b602088015173ffffffffffffffffffffffffffffffffffffffff8116612afc5760005b82811015612ae157878181518110612a9857612a986137fe565b6020026020010151600014612ad9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101612a7e565b508315612af157612af1856131f9565b600092505050612dea565b6000808273ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906143bd565b905060005b84811015612c2b5760008a8281518110612b8f57612b8f6137fe565b6020026020010151905080600003612ba75750612c23565b82612bde576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b88811115612c18576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b978890039792909201915b600101612b73565b508715612d06576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906388e5b2d9908490612c88908e908e906004016143da565b60206040518083038185885af1158015612ca6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612ccb91906143bd565b612d01576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612dd5565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906391db0b7e908490612d5c908e908e906004016143da565b60206040518083038185885af1158015612d7a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d9f91906143bd565b612dd5576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8515612de457612de4876131f9565b50925050505b9695505050505050565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b01519451600099612e3599989796918c9101614493565b60405160208183030381529060405280519060200120905092915050565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612e35565b6000808251604103612ecb5760208301516040840151606085015160001a612ebf8782858561320c565b94509450505050612ed3565b506000905060025b9250929050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612f4e578515612f35576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612f4457612f44846131f9565b6000915050612dea565b8515613039578073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc391906143bd565b612ff9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115613033576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393505b8415613111576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890613093908b90600401613771565b60206040518083038185885af11580156130b1573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906130d691906143bd565b61310c576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131de565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890613165908b90600401613771565b60206040518083038185885af1158015613183573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906131a891906143bd565b6131de576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156131ed576131ed846131f9565b50939695505050505050565b8015613209576132093382613324565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613243575060009050600361331b565b8460ff16601b1415801561325b57508460ff16601c14155b1561326c575060009050600461331b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156132c0573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133145760006001925092505061331b565b9150600090505b94509492505050565b80471015613393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146133ed576040519150601f19603f3d011682016040523d82523d6000602084013e6133f2565b606091505b5050905080610a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161338a565b60008083601f84011261349557600080fd5b50813567ffffffffffffffff8111156134ad57600080fd5b6020830191508360208260051b8501011115612ed357600080fd5b600080602083850312156134db57600080fd5b823567ffffffffffffffff8111156134f257600080fd5b6134fe85828601613483565b90969095509350505050565b60005b8381101561352557818101518382015260200161350d565b50506000910152565b6000815180845261354681602086016020860161350a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129fc602083018461352e565b73ffffffffffffffffffffffffffffffffffffffff8116811461320957600080fd5b80356135b88161358b565b919050565b6000602082840312156135cf57600080fd5b81356129fc8161358b565b6000602082840312156135ec57600080fd5b813567ffffffffffffffff81111561360357600080fd5b820160e081850312156129fc57600080fd5b6020808252825182820181905260009190848201906040850190845b8181101561364d57835183529284019291840191600101613631565b50909695505050505050565b60006060828403121561366b57600080fd5b50919050565b60006020828403121561368357600080fd5b5035919050565b6000610140825184526020830151602085015260408301516136b8604086018267ffffffffffffffff169052565b5060608301516136d4606086018267ffffffffffffffff169052565b5060808301516136f0608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161372260c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161374a60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b506101008381015115159085015261012080840151818601839052612dea8387018261352e565b6020815260006129fc602083018461368a565b6000610100828403121561366b57600080fd5b600080604083850312156137aa57600080fd5b82356137b58161358b565b946020939093013593505050565b6000602082840312156137d557600080fd5b813567ffffffffffffffff8111156137ec57600080fd5b8201604081850312156129fc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261386157600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156138bd576138bd61386b565b60405290565b60405160c0810167ffffffffffffffff811182821017156138bd576138bd61386b565b6040516080810167ffffffffffffffff811182821017156138bd576138bd61386b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156139505761395061386b565b604052919050565b600067ffffffffffffffff8211156139725761397261386b565b5060051b60200190565b60006040828403121561398e57600080fd5b6040516040810181811067ffffffffffffffff821117156139b1576139b161386b565b604052823581526020928301359281019290925250919050565b6000606082840312156139dd57600080fd5b6040516060810181811067ffffffffffffffff82111715613a0057613a0061386b565b604052905080823560ff81168114613a1757600080fd5b8082525060208301356020820152604083013560408201525092915050565b600082601f830112613a4757600080fd5b81356020613a5c613a5783613958565b613909565b82815260609283028501820192828201919087851115613a7b57600080fd5b8387015b85811015613a9e57613a9189826139cb565b8452928401928101613a7f565b5090979650505050505050565b803567ffffffffffffffff811681146135b857600080fd5b600060a08236031215613ad557600080fd5b613add61389a565b8235815260208084013567ffffffffffffffff80821115613afd57600080fd5b9085019036601f830112613b1057600080fd5b8135613b1e613a5782613958565b81815260069190911b83018401908481019036831115613b3d57600080fd5b938501935b82851015613b6657613b54368661397c565b82528582019150604085019450613b42565b80868801525050506040860135925080831115613b8257600080fd5b5050613b9036828601613a36565b604083015250613ba2606084016135ad565b6060820152613bb360808401613aab565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561072a5761072a613bbe565b801515811461320957600080fd5b600067ffffffffffffffff821115613c2857613c2861386b565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600060c08284031215613c6657600080fd5b613c6e6138c3565b90508135613c7b8161358b565b81526020613c8a838201613aab565b818301526040830135613c9c81613c00565b604083015260608381013590830152608083013567ffffffffffffffff811115613cc557600080fd5b8301601f81018513613cd657600080fd5b8035613ce4613a5782613c0e565b8181528684838501011115613cf857600080fd5b818484018583013760008483830101528060808601525050505060a082013560a082015292915050565b600060e08236031215613d3457600080fd5b613d3c61389a565b82358152602083013567ffffffffffffffff811115613d5a57600080fd5b613d6636828601613c54565b602083015250613d7936604085016139cb565b604082015260a0830135613d8c8161358b565b6060820152613bb360c08401613aab565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261386157600080fd5b600061072a3683613c54565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261386157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e4657600080fd5b83018035915067ffffffffffffffff821115613e6157600080fd5b6020019150600581901b3603821315612ed357600080fd5b6000613e87613a5784613958565b80848252602080830192508560051b850136811115613ea557600080fd5b855b81811015613ee157803567ffffffffffffffff811115613ec75760008081fd5b613ed336828a01613c54565b865250938201938201613ea7565b50919695505050505050565b600060408284031215613eff57600080fd5b6129fc838361397c565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613f3e57600080fd5b83018035915067ffffffffffffffff821115613f5957600080fd5b6020019150600681901b3603821315612ed357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fa657600080fd5b83018035915067ffffffffffffffff821115613fc157600080fd5b6020019150606081023603821315612ed357600080fd5b600060608284031215613fea57600080fd5b6129fc83836139cb565b60006020828403121561400657600080fd5b6129fc82613aab565b600181811c9082168061402357607f821691505b60208210810361366b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000610100828403121561406f57600080fd5b61407761389a565b82358152614088846020850161397c565b602082015261409a84606085016139cb565b604082015260c08301356140ad8161358b565b60608201526140be60e08401613aab565b60808201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140fb576140fb613bbe565b5060010190565b6000602080838503121561411557600080fd5b825167ffffffffffffffff8082111561412d57600080fd5b908401906080828703121561414157600080fd5b6141496138e6565b825181528383015161415a8161358b565b81850152604083015161416c81613c00565b604082015260608301518281111561418357600080fd5b80840193505086601f84011261419857600080fd5b825191506141a8613a5783613c0e565b82815287858486010111156141bc57600080fd5b6141cb8386830187870161350a565b60608201529695505050505050565b601f821115610a6357600081815260208120601f850160051c810160208610156142015750805b601f850160051c820191505b818110156142205782815560010161420d565b505050505050565b815167ffffffffffffffff8111156142425761424261386b565b61425681614250845461400f565b846141da565b602080601f8311600181146142a957600084156142735750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614220565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f6578886015182559484019460019091019084016142d7565b508582101561433257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061438a604083018461352e565b949350505050565b6000825161386181846020870161350a565b6000602082840312156143b657600080fd5b5051919050565b6000602082840312156143cf57600080fd5b81516129fc81613c00565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561444f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261443d86835161368a565b95509382019390820190600101614403565b50508584038187015286518085528782019482019350915060005b828110156144865784518452938101939281019260010161446a565b5091979650505050505050565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161452c81607985016020880161350a565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a995050505050505050505056fea164736f6c6343000813000a
Deployed Bytecode
0x60806040526004361061018b5760003560e01c806395411525116100d6578063d45c44351161007f578063ed24911d11610059578063ed24911d146104fd578063f10b5cc814610512578063f17325e71461054157600080fd5b8063d45c443514610467578063e30bb5631461049e578063e71ff365146104dd57600080fd5b8063b469318d116100b0578063b469318d146103ba578063b83010d314610414578063cf190f341461044757600080fd5b80639541152514610367578063a3112a641461037a578063a6d4dbc7146103a757600080fd5b806344adc90e116101385780634d003070116101125780634d003070146102de57806354fd4d50146102fe57806379f7573a1461034757600080fd5b806344adc90e1461029857806346926267146102b85780634cb7e9e5146102cb57600080fd5b806317d7de7c1161016957806317d7de7c146102205780632d0335ab146102425780633c0427151461028557600080fd5b80630eabf6601461019057806312b11a17146101a557806313893f61146101e7575b600080fd5b6101a361019e3660046134c8565b610554565b005b3480156101b157600080fd5b507ffeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d9880765b6040519081526020015b60405180910390f35b3480156101f357600080fd5b506102076102023660046134c8565b6106eb565b60405167ffffffffffffffff90911681526020016101de565b34801561022c57600080fd5b50610235610730565b6040516101de9190613578565b34801561024e57600080fd5b506101d461025d3660046135bd565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101d46102933660046135da565b610760565b6102ab6102a63660046134c8565b610863565b6040516101de9190613615565b6101a36102c6366004613659565b6109e4565b6101a36102d93660046134c8565b610a68565b3480156102ea57600080fd5b506102076102f9366004613671565b610b4b565b34801561030a57600080fd5b506102356040518060400160405280600c81526020017f312e342e312d626574612e31000000000000000000000000000000000000000081525081565b34801561035357600080fd5b506101a3610362366004613671565b610b58565b6102ab6103753660046134c8565b610bef565b34801561038657600080fd5b5061039a610395366004613671565b610e62565b6040516101de9190613771565b6101a36103b5366004613784565b611025565b3480156103c657600080fd5b506102076103d5366004613797565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561042057600080fd5b507fb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e756101d4565b34801561045357600080fd5b50610207610462366004613671565b6110ca565b34801561047357600080fd5b50610207610482366004613671565b60009081526033602052604090205467ffffffffffffffff1690565b3480156104aa57600080fd5b506104cd6104b9366004613671565b600090815260326020526040902054151590565b60405190151581526020016101de565b3480156104e957600080fd5b506102076104f83660046134c8565b6110d8565b34801561050957600080fd5b506101d4611110565b34801561051e57600080fd5b5060405173420000000000000000000000000000000000002081526020016101de565b6101d461054f3660046137c3565b61111a565b348160005b818110156106e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018114600086868481811061059a5761059a6137fe565b90506020028101906105ac919061382d565b6105b590613ac3565b60208101518051919250908015806105d257508260400151518114155b15610609576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106ad576106a56040518060a001604052808660000151815260200185848151811061063e5761063e6137fe565b6020026020010151815260200186604001518481518110610661576106616137fe565b60200260200101518152602001866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866080015167ffffffffffffffff168152506111d8565b60010161060c565b506106c383600001518385606001518a886113e9565b6106cd9088613bed565b9650505050506106dd8160010190565b9050610559565b5050505050565b60004282825b818110156107245761071c3387878481811061070f5761070f6137fe565b9050602002013585611a18565b6001016106f1565b50909150505b92915050565b606061075b7f4541530000000000000000000000000000000000000000000000000000000000611b17565b905090565b600061077361076e83613d22565b611ca5565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161078a5790505090506107f86020840184613d9d565b61080190613dd1565b81600081518110610814576108146137fe565b602090810291909101015261083d83358261083560c0870160a088016135bd565b346001611e2f565b60200151600081518110610853576108536137fe565b6020026020010151915050919050565b60608160008167ffffffffffffffff8111156108815761088161386b565b6040519080825280602002602001820160405280156108b457816020015b606081526020019060019003908161089f5790505b509050600034815b848110156109ce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85018114368989848181106108fc576108fc6137fe565b905060200281019061090e9190613ddd565b905061091d6020820182613e11565b9050600003610958576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061097d823561096c6020850185613e11565b61097591613e79565b338887611e2f565b805190915061098c9086613bed565b945080602001518785815181106109a5576109a56137fe565b6020026020010181905250806020015151860195505050506109c78160010190565b90506108bc565b506109d98383612541565b979650505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816109fb579050509050610a3636839003830160208401613eed565b81600081518110610a4957610a496137fe565b6020908102919091010152610a63823582333460016113e9565b505050565b348160005b818110156106e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201811436868684818110610aad57610aad6137fe565b9050602002810190610abf9190613ddd565b9050610b2c8135610ad36020840184613f09565b808060200260200160405190810160405280939291908181526020016000905b82821015610b1f57610b1060408302860136819003810190613eed565b81526020019060010190610af3565b50505050503388866113e9565b610b369086613bed565b94505050610b448160010190565b9050610a6d565b60004261072a838261262b565b33600090815260208190526040902054808211610ba1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152602081815260409182902084905581518381529081018490527f57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7910160405180910390a15050565b60608160008167ffffffffffffffff811115610c0d57610c0d61386b565b604051908082528060200260200182016040528015610c4057816020015b6060815260200190600190039081610c2b5790505b509050600034815b848110156109ce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501811436898984818110610c8857610c886137fe565b9050602002810190610c9a919061382d565b9050366000610cac6020840184613e11565b909250905080801580610ccd5750610cc76040850185613f71565b90508114155b15610d04576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610de557610ddd6040518060a0016040528087600001358152602001868685818110610d3957610d396137fe565b9050602002810190610d4b9190613d9d565b610d5490613dd1565b8152602001610d666040890189613f71565b85818110610d7657610d766137fe565b905060600201803603810190610d8c9190613fd8565b8152602001610da16080890160608a016135bd565b73ffffffffffffffffffffffffffffffffffffffff168152602001610dcc60a0890160808a01613ff4565b67ffffffffffffffff169052611ca5565b600101610d07565b506000610e0e8535610df78587613e79565b610e076080890160608a016135bd565b8b8a611e2f565b8051909150610e1d9089613bed565b975080602001518a8881518110610e3657610e366137fe565b602002602001018190525080602001515189019850505050505050610e5b8160010190565b9050610c48565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610f9c9061400f565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc89061400f565b80156110155780601f10610fea57610100808354040283529160200191611015565b820191906000526020600020905b815481529060010190602001808311610ff857829003601f168201915b5050505050815250509050919050565b61103c6110373683900383018361405c565b6111d8565b604080516001808252818301909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161105357905050905061108e36839003830160208401613eed565b816000815181106110a1576110a16137fe565b6020908102919091010152610a638235826110c260e0860160c087016135bd565b3460016113e9565b60004261072a338483611a18565b60004282825b81811015610724576111088686838181106110fb576110fb6137fe565b905060200201358461262b565b6001016110de565b600061075b6126ed565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816111345790505090506111a26020840184613d9d565b6111ab90613dd1565b816000815181106111be576111be6137fe565b602090810291909101015261083d83358233346001611e2f565b608081015167ffffffffffffffff161580159061120c57504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611243576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401516060850151855184518587015173ffffffffffffffffffffffffffffffffffffffff84166000908152978890529487208054969794969495611337957fb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e7595949392886112ba836140ca565b909155506080808c015160408051602081019990995273ffffffffffffffffffffffffffffffffffffffff9097169688019690965260608701949094529285019190915260a084015260c083015267ffffffffffffffff1660e0820152610100015b60405160208183030381529060405280519060200120612821565b90506113ad84606001518284602001518560400151866000015160405160200161139993929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604051602081830303815290604052612834565b6113e3576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611457573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261149d9190810190614102565b80519091506114d8576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff8111156114f5576114f561386b565b60405190808252806020026020018201604052801561159457816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115135790505b50905060008267ffffffffffffffff8111156115b2576115b261386b565b6040519080825280602002602001820160405280156115db578160200160208202803683370190505b50905060005b838110156119fa5760008a82815181106115fd576115fd6137fe565b6020908102919091018101518051600090815260329092526040909120805491925090611656576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611693576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c81169116146116e9576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff1661173f576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611799576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805483916101208401916118a59061400f565b80601f01602080910402602001604051908101604052809291908181526020018280546118d19061400f565b801561191e5780601f106118f35761010080835404028352916020019161191e565b820191906000526020600020905b81548152906001019060200180831161190157829003601f168201915b505050505081525050858481518110611939576119396137fe565b6020026020010181905250816020015184848151811061195b5761195b6137fe565b6020026020010181815250508c8b73ffffffffffffffffffffffffffffffffffffffff16868581518110611991576119916137fe565b602002602001015160c0015173ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f61585600001516040516119e891815260200190565b60405180910390a450506001016115e1565b50611a0a84838360018b8b612a03565b9a9950505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611a8c576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b6020811015611be2576000858260208110611b5d57611b5d6137fe565b1a60f81b90507fff000000000000000000000000000000000000000000000000000000000000008116600003611b935750611be2565b80848481518110611ba657611ba66137fe565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060019182019101611b40565b5060008167ffffffffffffffff811115611bfe57611bfe61386b565b6040519080825280601f01601f191660200182016040528015611c28576020820181803683370190505b50905060005b82811015611c9c57838181518110611c4857611c486137fe565b602001015160f81c60f81b828281518110611c6557611c656137fe565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611c2e565b50949350505050565b608081015167ffffffffffffffff1615801590611cd957504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611d10576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401516060808601518651855186880151868801519488015160808901518051908b012060a08a015173ffffffffffffffffffffffffffffffffffffffff871660009081529b8c9052988b2080549a9b989a9899611337997ffeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d988076999493928c611da0836140ca565b919050558e6080015160405160200161131c9b9a999897969594939291909a8b5273ffffffffffffffffffffffffffffffffffffffff998a1660208c015260408b019890985295909716606089015267ffffffffffffffff938416608089015291151560a088015260c087015260e0860152610100850193909352610120840152166101408201526101600190565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff811115611e7457611e7461386b565b604051908082528060200260200182016040528015611e9d578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611f0f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f559190810190614102565b8051909150611f90576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff811115611fab57611fab61386b565b60405190808252806020026020018201604052801561204a57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611fc95790505b50905060008467ffffffffffffffff8111156120685761206861386b565b604051908082528060200260200182016040528015612091578160200160208202803683370190505b50905060005b858110156125205760008b82815181106120b3576120b36137fe565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff16141580156120fe57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15612135576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151158015612148575080604001515b1561217f576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016121a34290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6122458382612df4565b600081815260326020526040902054909250156122645760010161223b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906123e49082614228565b50505060608401511561243b57606084015160009081526032602052604090205461243b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8287868151811061244e5761244e6137fe565b60200260200101819052508360a00151868681518110612470576124706137fe565b6020026020010181815250508189602001518681518110612493576124936137fe565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b358560405161250391815260200190565b60405180910390a4505050506125198160010190565b9050612097565b5061253083838360008c8c612a03565b845250919998505050505050505050565b606060008267ffffffffffffffff81111561255e5761255e61386b565b604051908082528060200260200182016040528015612587578160200160208202803683370190505b508451909150600090815b818110156126205760008782815181106125ae576125ae6137fe565b6020026020010151905060008151905060005b8181101561260c578281815181106125db576125db6137fe565b60200260200101518787815181106125f5576125f56137fe565b6020908102919091010152600195860195016125c1565b5050506126198160010190565b9050612592565b509195945050505050565b60008281526033602052604090205467ffffffffffffffff161561267b576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000009101223d33eeaea94045bb2920f00ba0f7a475bc1614801561275357507f00000000000000000000000000000000000000000000000000000000000b67d246145b1561277d57507ff8fb232858d8ad10fc42a30f144b1d6b4494961ffc5afd1f35cd47572228de0590565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f9fed719e0073f95229e6f4f6b6f28f260c524ab08aa40b11f9c28cb710d7c72a828401527f6a08c3e203132c561752255a4d52ffae85bb9c5d33cb3291520dea1b8435638960608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b600061072a61282e6126ed565b83612e53565b60008060006128438585612e95565b9092509050600081600481111561285c5761285c614342565b14801561289457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156128a4576001925050506129fc565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016128d9929190614371565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516129629190614392565b600060405180830381855afa9150503d806000811461299d576040519150601f19603f3d011682016040523d82523d6000602084013e6129a2565b606091505b50915091508180156129b5575080516020145b80156129f5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906129f390830160209081019084016143a4565b145b9450505050505b9392505050565b84516000906001819003612a5b57612a538888600081518110612a2857612a286137fe565b602002602001015188600081518110612a4357612a436137fe565b6020026020010151888888612eda565b915050612dea565b602088015173ffffffffffffffffffffffffffffffffffffffff8116612afc5760005b82811015612ae157878181518110612a9857612a986137fe565b6020026020010151600014612ad9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101612a7e565b508315612af157612af1856131f9565b600092505050612dea565b6000808273ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906143bd565b905060005b84811015612c2b5760008a8281518110612b8f57612b8f6137fe565b6020026020010151905080600003612ba75750612c23565b82612bde576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b88811115612c18576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b978890039792909201915b600101612b73565b508715612d06576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906388e5b2d9908490612c88908e908e906004016143da565b60206040518083038185885af1158015612ca6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612ccb91906143bd565b612d01576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612dd5565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906391db0b7e908490612d5c908e908e906004016143da565b60206040518083038185885af1158015612d7a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d9f91906143bd565b612dd5576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8515612de457612de4876131f9565b50925050505b9695505050505050565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b01519451600099612e3599989796918c9101614493565b60405160208183030381529060405280519060200120905092915050565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612e35565b6000808251604103612ecb5760208301516040840151606085015160001a612ebf8782858561320c565b94509450505050612ed3565b506000905060025b9250929050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612f4e578515612f35576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612f4457612f44846131f9565b6000915050612dea565b8515613039578073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc391906143bd565b612ff9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115613033576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393505b8415613111576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890613093908b90600401613771565b60206040518083038185885af11580156130b1573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906130d691906143bd565b61310c576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131de565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890613165908b90600401613771565b60206040518083038185885af1158015613183573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906131a891906143bd565b6131de576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156131ed576131ed846131f9565b50939695505050505050565b8015613209576132093382613324565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613243575060009050600361331b565b8460ff16601b1415801561325b57508460ff16601c14155b1561326c575060009050600461331b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156132c0573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133145760006001925092505061331b565b9150600090505b94509492505050565b80471015613393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146133ed576040519150601f19603f3d011682016040523d82523d6000602084013e6133f2565b606091505b5050905080610a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161338a565b60008083601f84011261349557600080fd5b50813567ffffffffffffffff8111156134ad57600080fd5b6020830191508360208260051b8501011115612ed357600080fd5b600080602083850312156134db57600080fd5b823567ffffffffffffffff8111156134f257600080fd5b6134fe85828601613483565b90969095509350505050565b60005b8381101561352557818101518382015260200161350d565b50506000910152565b6000815180845261354681602086016020860161350a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129fc602083018461352e565b73ffffffffffffffffffffffffffffffffffffffff8116811461320957600080fd5b80356135b88161358b565b919050565b6000602082840312156135cf57600080fd5b81356129fc8161358b565b6000602082840312156135ec57600080fd5b813567ffffffffffffffff81111561360357600080fd5b820160e081850312156129fc57600080fd5b6020808252825182820181905260009190848201906040850190845b8181101561364d57835183529284019291840191600101613631565b50909695505050505050565b60006060828403121561366b57600080fd5b50919050565b60006020828403121561368357600080fd5b5035919050565b6000610140825184526020830151602085015260408301516136b8604086018267ffffffffffffffff169052565b5060608301516136d4606086018267ffffffffffffffff169052565b5060808301516136f0608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161372260c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161374a60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b506101008381015115159085015261012080840151818601839052612dea8387018261352e565b6020815260006129fc602083018461368a565b6000610100828403121561366b57600080fd5b600080604083850312156137aa57600080fd5b82356137b58161358b565b946020939093013593505050565b6000602082840312156137d557600080fd5b813567ffffffffffffffff8111156137ec57600080fd5b8201604081850312156129fc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261386157600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156138bd576138bd61386b565b60405290565b60405160c0810167ffffffffffffffff811182821017156138bd576138bd61386b565b6040516080810167ffffffffffffffff811182821017156138bd576138bd61386b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156139505761395061386b565b604052919050565b600067ffffffffffffffff8211156139725761397261386b565b5060051b60200190565b60006040828403121561398e57600080fd5b6040516040810181811067ffffffffffffffff821117156139b1576139b161386b565b604052823581526020928301359281019290925250919050565b6000606082840312156139dd57600080fd5b6040516060810181811067ffffffffffffffff82111715613a0057613a0061386b565b604052905080823560ff81168114613a1757600080fd5b8082525060208301356020820152604083013560408201525092915050565b600082601f830112613a4757600080fd5b81356020613a5c613a5783613958565b613909565b82815260609283028501820192828201919087851115613a7b57600080fd5b8387015b85811015613a9e57613a9189826139cb565b8452928401928101613a7f565b5090979650505050505050565b803567ffffffffffffffff811681146135b857600080fd5b600060a08236031215613ad557600080fd5b613add61389a565b8235815260208084013567ffffffffffffffff80821115613afd57600080fd5b9085019036601f830112613b1057600080fd5b8135613b1e613a5782613958565b81815260069190911b83018401908481019036831115613b3d57600080fd5b938501935b82851015613b6657613b54368661397c565b82528582019150604085019450613b42565b80868801525050506040860135925080831115613b8257600080fd5b5050613b9036828601613a36565b604083015250613ba2606084016135ad565b6060820152613bb360808401613aab565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561072a5761072a613bbe565b801515811461320957600080fd5b600067ffffffffffffffff821115613c2857613c2861386b565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600060c08284031215613c6657600080fd5b613c6e6138c3565b90508135613c7b8161358b565b81526020613c8a838201613aab565b818301526040830135613c9c81613c00565b604083015260608381013590830152608083013567ffffffffffffffff811115613cc557600080fd5b8301601f81018513613cd657600080fd5b8035613ce4613a5782613c0e565b8181528684838501011115613cf857600080fd5b818484018583013760008483830101528060808601525050505060a082013560a082015292915050565b600060e08236031215613d3457600080fd5b613d3c61389a565b82358152602083013567ffffffffffffffff811115613d5a57600080fd5b613d6636828601613c54565b602083015250613d7936604085016139cb565b604082015260a0830135613d8c8161358b565b6060820152613bb360c08401613aab565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261386157600080fd5b600061072a3683613c54565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261386157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e4657600080fd5b83018035915067ffffffffffffffff821115613e6157600080fd5b6020019150600581901b3603821315612ed357600080fd5b6000613e87613a5784613958565b80848252602080830192508560051b850136811115613ea557600080fd5b855b81811015613ee157803567ffffffffffffffff811115613ec75760008081fd5b613ed336828a01613c54565b865250938201938201613ea7565b50919695505050505050565b600060408284031215613eff57600080fd5b6129fc838361397c565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613f3e57600080fd5b83018035915067ffffffffffffffff821115613f5957600080fd5b6020019150600681901b3603821315612ed357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fa657600080fd5b83018035915067ffffffffffffffff821115613fc157600080fd5b6020019150606081023603821315612ed357600080fd5b600060608284031215613fea57600080fd5b6129fc83836139cb565b60006020828403121561400657600080fd5b6129fc82613aab565b600181811c9082168061402357607f821691505b60208210810361366b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000610100828403121561406f57600080fd5b61407761389a565b82358152614088846020850161397c565b602082015261409a84606085016139cb565b604082015260c08301356140ad8161358b565b60608201526140be60e08401613aab565b60808201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140fb576140fb613bbe565b5060010190565b6000602080838503121561411557600080fd5b825167ffffffffffffffff8082111561412d57600080fd5b908401906080828703121561414157600080fd5b6141496138e6565b825181528383015161415a8161358b565b81850152604083015161416c81613c00565b604082015260608301518281111561418357600080fd5b80840193505086601f84011261419857600080fd5b825191506141a8613a5783613c0e565b82815287858486010111156141bc57600080fd5b6141cb8386830187870161350a565b60608201529695505050505050565b601f821115610a6357600081815260208120601f850160051c810160208610156142015750805b601f850160051c820191505b818110156142205782815560010161420d565b505050505050565b815167ffffffffffffffff8111156142425761424261386b565b61425681614250845461400f565b846141da565b602080601f8311600181146142a957600084156142735750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614220565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f6578886015182559484019460019091019084016142d7565b508582101561433257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061438a604083018461352e565b949350505050565b6000825161386181846020870161350a565b6000602082840312156143b657600080fd5b5051919050565b6000602082840312156143cf57600080fd5b81516129fc81613c00565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561444f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261443d86835161368a565b95509382019390820190600101614403565b50508584038187015286518085528782019482019350915060005b828110156144865784518452938101939281019260010161446a565b5091979650505050505050565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161452c81607985016020880161350a565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a995050505050505050505056fea164736f6c6343000813000a
Deployed Bytecode Sourcemap
1322:28163:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11248:2406;;;;;;:::i;:::-;;:::i;:::-;;3062:100:10;;;;;;;;;;-1:-1:-1;1197:66:10;3062:100;;;1105:25:14;;;1093:2;1078:18;3062:100:10;;;;;;;;14069:308:7;;;;;;;;;;-1:-1:-1;14069:308:7;;;;;:::i;:::-;;:::i;:::-;;;1904:18:14;1892:31;;;1874:50;;1862:2;1847:18;14069:308:7;1730:200:14;3480:103:10;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;2817:107::-;;;;;;;;;;-1:-1:-1;2817:107:10;;;;;:::i;:::-;2901:16;;2875:7;2901:16;;;;;;;;;;;;2817:107;3259:423:7;;;;;;:::i;:::-;;:::i;3713:2268::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;9196:255::-;;;;;;:::i;:::-;;:::i;9872:1345::-;;;;;;:::i;:::-;;:::i;13685:150::-;;;;;;;;;;-1:-1:-1;13685:150:7;;;;;:::i;:::-;;:::i;2623:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3750:301:10;;;;;;;;;;-1:-1:-1;3750:301:10;;;;;:::i;:::-;;:::i;6012:3153:7:-;;;;;;:::i;:::-;;:::i;14725:112::-;;;;;;;;;;-1:-1:-1;14725:112:7;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;9482:359::-;;;;;;:::i;:::-;;:::i;15155:148::-;;;;;;;;;;-1:-1:-1;15155:148:7;;;;;:::i;:::-;15261:29;;;;;15236:6;15261:29;;;:20;:29;;;;;;;;:35;;;;;;;;;;;15155:148;3300:100:10;;;;;;;;;;-1:-1:-1;1524:66:10;3300:100;;13866:172:7;;;;;;;;;;-1:-1:-1;13866:172:7;;;;;:::i;:::-;;:::i;15016:108::-;;;;;;;;;;-1:-1:-1;15016:108:7;;;;;:::i;:::-;15075:6;15100:17;;;:11;:17;;;;;;;;;15016:108;14868:117;;;;;;;;;;-1:-1:-1;14868:117:7;;;;;:::i;:::-;14930:4;14953:8;;;:3;:8;;;;;:12;:25;;;14868:117;;;;9005:14:14;;8998:22;8980:41;;8968:2;8953:18;14868:117:7;8840:187:14;14408:286:7;;;;;;;;;;-1:-1:-1;14408:286:7;;;;;:::i;:::-;;:::i;2569:106:10:-;;;;;;;;;;;;;:::i;2798:108:7:-;;;;;;;;;;-1:-1:-1;2798:108:7;;3754:42:12;9202:74:14;;9190:2;9175:18;2798:108:7;9032:250:14;2937:291:7;;;;;;:::i;:::-;;:::i;11248:2406::-;11823:9;11860:22;11798;11899:1749;11923:6;11919:1;:10;11899:1749;;;12307:10;;;12302:15;;12244:9;12409:22;;12302:1;12409:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;12346:88;;;:::i;:::-;12486:26;;;;12598:11;;12346:88;;-1:-1:-1;12486:26:7;12627:15;;;:72;;;12660:21;:32;;;:39;12646:10;:53;;12627:72;12623:133;;;12726:15;;;;;;;;;;;;;;12623:133;12890:9;12885:496;12909:10;12905:1;:14;12885:496;;;12960:406;12995:353;;;;;;;;13056:21;:28;;;12995:353;;;;13116:4;13121:1;13116:7;;;;;;;;:::i;:::-;;;;;;;12995:353;;;;13160:21;:32;;;13193:1;13160:35;;;;;;;;:::i;:::-;;;;;;;12995:353;;;;13230:21;:29;;;12995:353;;;;;;13295:21;:30;;;12995:353;;;;;12960:13;:406::i;:::-;1638:1:6;1634:5;12885:496:7;;;;13541:96;13549:21;:28;;;13579:4;13585:21;:29;;;13616:14;13632:4;13541:7;:96::i;:::-;13507:130;;;;:::i;:::-;;;11952:1696;;;;11935:15;11948:1;1638::6;1634:5;;1546:102;11935:15:7;11931:19;;11899:1749;;;;11385:2269;;11248:2406;;:::o;14069:308::-;14141:6;6632:15:10;14208:4:7;14141:6;14229:120;14253:6;14249:1;:10;14229:120;;;14296:42;14312:10;14324:4;;14329:1;14324:7;;;;;;;:::i;:::-;;;;;;;14333:4;14296:15;:42::i;:::-;1638:1:6;1634:5;14229:120:7;;;-1:-1:-1;14366:4:7;;-1:-1:-1;;14069:308:7;;;;;:::o;3480:103:10:-;3522:13;3554:22;3570:5;3554:15;:22::i;:::-;3547:29;;3480:103;:::o;3259:423:7:-;3392:7;3415:31;;3429:16;3415:31;:::i;:::-;:13;:31::i;:::-;3496;;;3525:1;3496:31;;;;;;;;;3457:36;;3496:31;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3496:31:7;;;;;;;;;;;;;-1:-1:-1;3457:70:7;-1:-1:-1;3547:21:7;;;;:16;:21;:::i;:::-;3537:31;;;:::i;:::-;:4;3542:1;3537:7;;;;;;;;:::i;:::-;;;;;;;;;;:31;3585:82;3593:23;;3618:4;3624:25;;;;;;;;:::i;:::-;3651:9;3662:4;3585:7;:82::i;:::-;:87;;;3673:1;3585:90;;;;;;;;:::i;:::-;;;;;;;3578:97;;;3259:423;;;:::o;3713:2268::-;3834:16;4055:13;4038:14;4055:13;4116:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4085:54:7;-1:-1:-1;4149:22:7;4614:9;4149:22;4634:1210;4658:6;4654:1;:10;4634:1210;;;5042:10;;;5037:15;;5139:45;5187:13;;5037:1;5187:16;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;5139:64;-1:-1:-1;5267:17:7;;;;5139:64;5267:17;:::i;:::-;:24;;5295:1;5267:29;5263:90;;5323:15;;;;;;;;;;;;;;5263:90;5367:29;5415:81;5423:19;;5444:17;;;;5423:12;5444:17;:::i;:::-;5415:81;;;:::i;:::-;5463:10;5475:14;5491:4;5415:7;:81::i;:::-;5641:13;;5367:129;;-1:-1:-1;5623:31:7;;;;:::i;:::-;;;5736:3;:8;;;5721:9;5731:1;5721:12;;;;;;;;:::i;:::-;;;;;;:23;;;;5804:3;:8;;;:15;5786:33;;;;4687:1157;;;4670:15;4683:1;1638::6;1634:5;;1546:102;4670:15:7;4666:19;;4634:1210;;;;5937:37;5948:9;5959:14;5937:10;:37::i;:::-;5930:44;3713:2268;-1:-1:-1;;;;;;;3713:2268:7:o;9196:255::-;9313:30;;;9341:1;9313:30;;;;;;;;;9275:35;;9313:30;;;;-1:-1:-1;;;;;;;;;;;;;;;;;9313:30:7;;;;;;;;;;;;;;-1:-1:-1;9275:68:7;-1:-1:-1;9353:22:7;;;;;;;9363:12;;;9353:22;:::i;:::-;:4;9358:1;9353:7;;;;;;;;:::i;:::-;;;;;;;;;;:22;9386:58;9394:14;;9410:4;9416:10;9428:9;9439:4;9386:7;:58::i;:::-;;9265:186;9196:255;:::o;9872:1345::-;10397:9;10434:13;10372:22;10464:747;10488:6;10484:1;:10;10464:747;;;10872:10;;;10867:15;;10911:44;10958:13;;10867:1;10958:16;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;10911:63;-1:-1:-1;11119:81:7;11127:19;;11148:17;;;;10911:63;11148:17;:::i;:::-;11119:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;11167:10;11179:14;11195:4;11119:7;:81::i;:::-;11101:99;;;;:::i;:::-;;;10517:694;;10500:15;10513:1;1638::6;1634:5;;1546:102;10500:15:7;10496:19;;10464:747;;13685:150;13736:6;6632:15:10;13785:22:7;13796:4;6632:15:10;13785:10:7;:22::i;3750:301:10:-;3837:10;3810:16;3829:19;;;;;;;;;;;3862:20;;;3858:72;;3905:14;;;;;;;;;;;;;;3858:72;3948:10;3940:7;:19;;;;;;;;;;;;:30;;;3986:58;;22379:25:14;;;22420:18;;;22413:34;;;3986:58:10;;22352:18:14;3986:58:10;;;;;;;3800:251;3750:301;:::o;6012:3153:7:-;6163:16;6384:22;6367:14;6384:22;6454:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6423:54:7;-1:-1:-1;6487:22:7;6952:9;6487:22;6972:2056;6996:6;6992:1;:10;6972:2056;;;7380:10;;;7375:15;;7419:63;7485:22;;7375:1;7485:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;7419:91;-1:-1:-1;7524:38:7;;7565:26;;;;7419:91;7565:26;:::i;:::-;7524:67;;-1:-1:-1;7524:67:7;-1:-1:-1;7524:67:7;7706:15;;;:72;;-1:-1:-1;7739:32:7;;;;:21;:32;:::i;:::-;:39;;7725:10;:53;;7706:72;7702:133;;;7805:15;;;;;;;;;;;;;;7702:133;7969:9;7964:499;7988:10;7984:1;:14;7964:499;;;8039:409;8074:356;;;;;;;;8136:21;:28;;;8074:356;;;;8196:4;;8201:1;8196:7;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;8074:356;;;:::i;:::-;;;;;8240:32;;;;:21;:32;:::i;:::-;8273:1;8240:35;;;;;;;:::i;:::-;;;;;;8074:356;;;;;;;;;;:::i;:::-;;;;;8311:30;;;;;;;;:::i;:::-;8074:356;;;;;;8377:30;;;;;;;;:::i;:::-;8074:356;;;;8039:13;:409::i;:::-;1638:1:6;1634:5;7964:499:7;;;-1:-1:-1;8535:29:7;8583:97;8591:28;;8583:97;8621:4;;8583:97;:::i;:::-;8627:30;;;;;;;;:::i;:::-;8659:14;8675:4;8583:7;:97::i;:::-;8825:13;;8535:145;;-1:-1:-1;8807:31:7;;;;:::i;:::-;;;8920:3;:8;;;8905:9;8915:1;8905:12;;;;;;;;:::i;:::-;;;;;;:23;;;;8988:3;:8;;;:15;8970:33;;;;7025:2003;;;;;;7008:15;7021:1;1638::6;1634:5;;1546:102;7008:15:7;7004:19;;6972:2056;;14725:112;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14822:8:7;;;;:3;:8;;;;;;;;;14815:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14822:8;14815:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14725:112;;;:::o;9482:359::-;9591:31;;;;;;;;9605:16;9591:31;:::i;:::-;:13;:31::i;:::-;9671:30;;;9699:1;9671:30;;;;;;;;;9633:35;;9671:30;;;;-1:-1:-1;;;;;;;;;;;;;;;;;9671:30:7;;;;;;;;;;;;;;-1:-1:-1;9633:68:7;-1:-1:-1;9711:31:7;;;;;;;9721:21;;;9711:31;:::i;:::-;:4;9716:1;9711:7;;;;;;;;:::i;:::-;;;;;;;;;;:31;9753:81;9761:23;;9786:4;9792:24;;;;;;;;:::i;:::-;9818:9;9829:4;9753:7;:81::i;13866:172::-;13922:6;6632:15:10;13971:39:7;13987:10;13999:4;6632:15:10;13971::7;:39::i;14408:286::-;14475:6;6632:15:10;14542:4:7;14475:6;14563:103;14587:6;14583:1;:10;14563:103;;;14630:25;14641:4;;14646:1;14641:7;;;;;;;:::i;:::-;;;;;;;14650:4;14630:10;:25::i;:::-;1638:1:6;1634:5;14563:103:7;;2569:106:10;2622:7;2648:20;:18;:20::i;2937:291:7:-;3074:31;;;3103:1;3074:31;;;;;;;;;3016:7;;;;3074:31;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3074:31:7;;;;;;;;;;;;;-1:-1:-1;3035:70:7;-1:-1:-1;3125:12:7;;;;:7;:12;:::i;:::-;3115:22;;;:::i;:::-;:4;3120:1;3115:7;;;;;;;;:::i;:::-;;;;;;;;;;:22;3155:58;3163:14;;3179:4;3185:10;3197:9;3208:4;3155:7;:58::i;5442:956:10:-;5531:16;;;;:38;;;;;;:68;;-1:-1:-1;6632:15:10;5573:26;;:7;:16;;;:26;;;5531:68;5527:123;;;5622:17;;;;;;;;;;;;;;5527:123;5696:12;;;;;5747:17;;;;;5916:15;;;;5953:14;;5989:8;;6019:10;;;;6051:24;;;5660:33;6051:24;;;;;;;;;;:26;;5696:12;;5747:17;;5660:33;;5790:367;;1524:66;;5916:15;5953:14;5989:8;5660:33;6051:26;;;:::i;:::-;;;;-1:-1:-1;6099:16:10;;;;;5847:286;;;;;;25599:25:14;;;;25672:42;25660:55;;;25640:18;;;25633:83;;;;-1:-1:-1;25732:18:14;;25725:34;;;;25775:18;;;25768:34;;;;25818:19;;;25811:35;25862:19;;;25855:35;25939:18;25927:31;25906:19;;;25899:60;25571:19;;5847:286:10;;;;;;;;;;;;;5820:327;;;;;;5790:16;:367::i;:::-;5775:382;;6185:146;6239:7;:15;;;6256:4;6279:9;:11;;;6292:9;:11;;;6305:9;:11;;;6262:55;;;;;;;;;26151:19:14;;;26195:2;26186:12;;26179:28;;;;26245:3;26241:16;26259:66;26237:89;26232:2;26223:12;;26216:111;26352:2;26343:12;;25970:391;6262:55:10;;;;;;;;;;;;;6185:36;:146::i;:::-;6167:225;;6363:18;;;;;;;;;;;;;;6167:225;5517:881;;;5442:956;:::o;19180:2192:7:-;19517:36;;;;;;;;1105:25:14;;;19384:7:7;;;;3754:42:12;;19517:25:7;;1078:18:14;;19517:36:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19567:16;;19482:71;;-1:-1:-1;19563:82:7;;19619:15;;;;;;;;;;;;;;19563:82;19672:11;;19655:14;19672:11;19729:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19729:25:7;;;;;;;;;;;;;;;19693:61;;19764:23;19804:6;19790:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19790:21:7;;19764:47;;19827:9;19822:1442;19846:6;19842:1;:10;19822:1442;;;19889:36;19928:4;19933:1;19928:7;;;;;;;;:::i;:::-;;;;;;;;;;;;19988:11;;19950:31;19984:16;;;:3;:16;;;;;;;20105:15;;19928:7;;-1:-1:-1;19984:16:7;20101:84;;20160:10;;;;;;;;;;;;;;20101:84;20297:9;20275:11;:18;;;:31;20271:92;;20333:15;;;;;;;;;;;;;;20271:92;20456:20;;;;:31;;;;:20;;:31;20452:91;;20514:14;;;;;;;;;;;;;;20452:91;20769:21;;;;;;;;;20764:81;;20817:13;;;;;;;;;;;;;;20764:81;20945:26;;;;;;;;;:31;20941:93;;21003:16;;;;;;;;;;;;;;20941:93;6632:15:10;21047:26:7;;;:36;;;;;;;;;;;;;;;;;;;21098:29;;;;;;;;;;;;-1:-1:-1;21098:29:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21047:36;21098:29;;;;;;;;21047:26;;21098:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:12;21111:1;21098:15;;;;;;;;:::i;:::-;;;;;;:29;;;;21153:7;:13;;;21141:6;21148:1;21141:9;;;;;;;;:::i;:::-;;;;;;:25;;;;;21243:9;21221:7;21186:67;;21194:12;21207:1;21194:15;;;;;;;;:::i;:::-;;;;;;;:25;;;21186:67;;;21230:7;:11;;;21186:67;;;;1105:25:14;;1093:2;1078:18;;959:177;21186:67:7;;;;;;;;-1:-1:-1;;1638:1:6;1634:5;19822:1442:7;;;;21281:84;21302:12;21316;21330:6;21338:4;21344:14;21360:4;21281:20;:84::i;:::-;21274:91;19180:2192;-1:-1:-1;;;;;;;;;;19180:2192:7:o;28217:368::-;28368:29;;;28304:61;28368:29;;;:20;:29;;;;;;;;28412:17;;;;;;;;;;;;;:22;28408:84;;28457:24;;;;;;;;;;;;;;28408:84;28502:17;;;;;;;;;;;;:24;;;;;;;;;;;;;28542:36;;28502:24;;:17;;28542:36;;;;;;;28294:291;28217:368;;;:::o;2102:563:6:-;2201:13;;;2211:2;2201:13;;;;;;;;;2155;;2176:22;;2201:13;;;;;;;;;;;-1:-1:-1;2201:13:6;2176:38;;2221:14;2250:9;2245:218;2269:2;2265:1;:6;2245:218;;;2304:11;2318:4;2323:1;2318:7;;;;;;;:::i;:::-;;;;;-1:-1:-1;2339:12:6;;;2347:4;2339:12;2335:48;;2367:5;;;2335:48;2413:4;2393:9;2403:6;2393:17;;;;;;;;:::i;:::-;;;;:24;;;;;;;;;;-1:-1:-1;;1638:1:6;1634:5;;;;;2245:218;;;;2469:28;2510:6;2500:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2500:17:6;;2469:48;;2528:9;2523:103;2547:6;2543:1;:10;2523:103;;;2607:9;2617:1;2607:12;;;;;;;;:::i;:::-;;;;;;;;;2586:15;2602:1;2586:18;;;;;;;;:::i;:::-;;;;:33;;;;;;;;;;-1:-1:-1;1638:1:6;1634:5;2523:103;;;-1:-1:-1;2646:15:6;2102:563;-1:-1:-1;;;;2102:563:6:o;4188:1119:10:-;4278:16;;;;:38;;;;;;:68;;-1:-1:-1;6632:15:10;4320:26;;:7;:16;;;:26;;;4278:68;4274:123;;;4369:17;;;;;;;;;;;;;;4274:123;4444:12;;;;;4495:17;;;;;4664:16;;;;;4702:14;;4738;;4774:19;;;;4815:14;;;;4851:11;;;;4894:9;;;;4884:20;;;;;;4926:10;;;;4958:25;;;4407:34;4958:25;;;;;;;;;;:27;;4444:12;;4495:17;;4407:34;;4538:527;;1197:66;;4815:14;4851:11;4884:20;4407:34;4958:27;;;:::i;:::-;;;;;5007:7;:16;;;4595:446;;;;;;;;;;;;;;;;;28039:25:14;;;28083:42;28161:15;;;28156:2;28141:18;;28134:43;28208:2;28193:18;;28186:34;;;;28256:15;;;;28251:2;28236:18;;28229:43;28291:18;28346:15;;;28340:3;28325:19;;28318:44;28406:14;;28399:22;28393:3;28378:19;;28371:51;28453:3;28438:19;;28431:35;28497:3;28482:19;;28475:35;28541:3;28526:19;;28519:35;;;;28585:3;28570:19;;28563:35;28635:16;28629:3;28614:19;;28607:45;28026:3;28011:19;;27621:1037;15786:2918:7;-1:-1:-1;;;;;;;;;;;;;;;;;16050:11:7;;-1:-1:-1;;;;;;;;;16033:14:7;-1:-1:-1;;;;;;;16136:6:7;16122:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16122:21:7;-1:-1:-1;16111:8:7;;;:32;16269:36;;;;;;;;1105:25:14;;;16234:32:7;;3754:42:12;;16269:25:7;;1078:18:14;;16269:36:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16319:16;;16234:71;;-1:-1:-1;16315:82:7;;16371:15;;;;;;;;;;;;;;16315:82;16407:33;16461:6;16443:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16443:25:7;;;;;;;;;;;;;;;16407:61;;16478:23;16518:6;16504:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16504:21:7;;16478:47;;16541:9;16536:2029;16560:6;16556:1;:10;16536:2029;;;16603:37;16643:4;16648:1;16643:7;;;;;;;;:::i;:::-;;;;;;;16603:47;;239:1:6;16764:44:7;;:7;:22;;;:44;;;;:81;;;;-1:-1:-1;6632:15:10;16812:33:7;;:7;:22;;;:33;;;;16764:81;16760:150;;;16872:23;;;;;;;;;;;;;;16760:150;17033:12;:22;;;17032:23;:44;;;;;17059:7;:17;;;17032:44;17028:103;;;17103:13;;;;;;;;;;;;;;17028:103;17145:30;17178:420;;;;;;;;137:1:6;17213:9:7;;17178:420;;;;17248:9;17178:420;;;;17321:7;6632:15:10;;6552:103;17321:7:7;17178:420;;;;;;17362:7;:22;;;17178:420;;;;;;17418:1;17178:420;;;;;;17283:7;:14;;;17178:420;;;;17448:7;:17;;;17178:420;;;;;;17493:8;17178:420;;;;;;17530:7;:17;;;17178:420;;;;;;17571:7;:12;;;17178:420;;;17145:453;;17724:11;17749;17763:1;17749:15;;17778:247;17815:26;17823:11;17836:4;17815:7;:26::i;:::-;137:1:6;17863:8:7;;;:3;:8;;;;;:12;17809:32;;-1:-1:-1;17859:77:7;17912:5;17859:77;17986:6;;17778:247;;;18038:21;;;:15;18074:8;;;:3;:8;;;;;;;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18038:11;;18074:8;:22;;;;;;;;:::i;:::-;-1:-1:-1;;;18115:14:7;;;;:27;18111:256;;18278:14;;;;14930:4;14953:8;;;:3;:8;;;;;:12;18254:99;;18324:10;;;;;;;;;;;;;;18254:99;18399:11;18381:12;18394:1;18381:15;;;;;;;;:::i;:::-;;;;;;:29;;;;18436:7;:13;;;18424:6;18431:1;18424:9;;;;;;;;:::i;:::-;;;;;;:25;;;;;18478:3;18464;:8;;;18473:1;18464:11;;;;;;;;:::i;:::-;;;;;;:17;;;;;18544:9;18529:8;18501:53;;18510:7;:17;;;18501:53;;;18539:3;18501:53;;;;1105:25:14;;1093:2;1078:18;;959:177;18501:53:7;;;;;;;;16589:1976;;;;16572:15;16585:1;1638::6;1634:5;;1546:102;16572:15:7;16568:19;;16536:2029;;;;18591:85;18612:12;18626;18640:6;18648:5;18655:14;18671:4;18591:20;:85::i;:::-;18575:101;;-1:-1:-1;18575:101:7;;15786:2918;-1:-1:-1;;;;;;;;;15786:2918:7:o;28780:703::-;28870:16;28898:21;28936:9;28922:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28922:24:7;-1:-1:-1;29015:15:7;;28898:48;;-1:-1:-1;28957:20:7;;;29040:415;29064:13;29060:1;:17;29040:415;;;29114:28;29145:8;29154:1;29145:11;;;;;;;;:::i;:::-;;;;;;;29114:42;;29170:25;29198:11;:18;29170:46;;29235:9;29230:215;29254:17;29250:1;:21;29230:215;;;29333:11;29345:1;29333:14;;;;;;;;:::i;:::-;;;;;;;29312:4;29317:12;29312:18;;;;;;;;:::i;:::-;;;;;;;;;;:35;29398:14;;;;;1634:5:6;29230:215:7;;;;29100:355;;29083:15;29096:1;1638::6;1634:5;;1546:102;29083:15:7;29079:19;;29040:415;;;-1:-1:-1;29472:4:7;;28780:703;-1:-1:-1;;;;;28780:703:7:o;27791:225::-;27860:17;;;;:11;:17;;;;;;;;:22;27856:80;;27905:20;;;;;;;;;;;;;;27856:80;27946:17;;;;:11;:17;;;;;;:24;;;;;;;;;;;;;27986:23;;27946:24;;:17;;27986:23;;27946:17;27986:23;27791:225;;:::o;3143:308:5:-;3196:7;3227:4;3219:29;3236:12;3219:29;;:66;;;;;3269:16;3252:13;:33;3219:66;3215:230;;;-1:-1:-1;3308:24:5;;3143:308::o;3215:230::-;-1:-1:-1;3633:73:5;;;3392:10;3633:73;;;;35142:25:14;;;;3404:12:5;35183:18:14;;;35176:34;3418:15:5;35226:18:14;;;35219:34;3677:13:5;35269:18:14;;;35262:34;3700:4:5;35312:19:14;;;;35305:84;;;;3633:73:5;;;;;;;;;;35114:19:14;;;;3633:73:5;;;3623:84;;;;;;3480:103:10:o;4339:165:5:-;4416:7;4442:55;4464:20;:18;:20::i;:::-;4486:10;4442:21;:55::i;1039:667:4:-;1175:4;1192:17;1211:24;1239:33;1256:4;1262:9;1239:16;:33::i;:::-;1191:81;;-1:-1:-1;1191:81:4;-1:-1:-1;1295:26:4;1286:5;:35;;;;;;;;:::i;:::-;;:58;;;;;1338:6;1325:19;;:9;:19;;;1286:58;1282:100;;;1367:4;1360:11;;;;;;1282:100;1393:12;1407:19;1430:6;:17;;1484:34;;;1520:4;1526:9;1461:75;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1430:116;;;;1461:75;1430:116;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1392:154;;;;1564:7;:42;;;;;1587:6;:13;1604:2;1587:19;1564:42;:134;;;;-1:-1:-1;1622:29:4;;1663:34;;1622:29;;;;;;;;;;;;:::i;:::-;:76;1564:134;1556:143;;;;;;1039:667;;;;;;:::o;24114:2258:7:-;24419:19;;24379:7;;24462:1;24452:11;;;24448:146;;24486:97;24506:12;24520;24533:1;24520:15;;;;;;;;:::i;:::-;;;;;;;24537:6;24544:1;24537:9;;;;;;;;:::i;:::-;;;;;;;24548:12;24562:14;24578:4;24486:19;:97::i;:::-;24479:104;;;;;24448:146;24631:21;;;;24666:31;;;24662:406;;24795:9;24790:165;24814:6;24810:1;:10;24790:165;;;24865:6;24872:1;24865:9;;;;;;;;:::i;:::-;;;;;;;24878:1;24865:14;24861:80;;24910:12;;;;;;;;;;;;;;24861:80;1638:1:6;1634:5;24790:165:7;;;;24973:4;24969:66;;;24997:23;25005:14;24997:7;:23::i;:::-;25056:1;25049:8;;;;;;24662:406;25078:22;25114;25139:8;:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25114:45;;25175:9;25170:777;25194:6;25190:1;:10;25170:777;;;25237:13;25253:6;25260:1;25253:9;;;;;;;;:::i;:::-;;;;;;;25237:25;;25375:5;25384:1;25375:10;25371:57;;25405:8;;;25371:57;25447:17;25442:76;;25491:12;;;;;;;;;;;;;;25442:76;25634:14;25626:5;:22;25622:87;;;25675:19;;;;;;;;;;;;;;25622:87;25858:23;;;;;25899;;;;;25170:777;1638:1:6;1634:5;25170:777:7;;;;25961:12;25957:309;;;25994:67;;;;;:20;;;;;;26023:14;;25994:67;;26040:12;;26054:6;;25994:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25989:134;;26088:20;;;;;;;;;;;;;;25989:134;25957:309;;;26144:67;;;;;:20;;;;;;26173:14;;26144:67;;26190:12;;26204:6;;26144:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26139:127;;26234:21;;;;;;;;;;;;;;26139:127;26280:4;26276:58;;;26300:23;26308:14;26300:7;:23::i;:::-;-1:-1:-1;26351:14:7;-1:-1:-1;;;24114:2258:7;;;;;;;;;:::o;26583:502::-;26750:18;;;;;26786:21;;;;26825:20;;;;26863:16;;;;;26897:26;;;;26941:21;;;;26980:18;;;;27016:16;;;;26716:352;;26667:7;;26716:352;;26750:18;26786:21;26825:20;27016:16;27050:4;;26716:352;;:::i;:::-;;;;;;;;;;;;;26693:385;;;;;;26686:392;;26583:502;;;;:::o;8546:194:3:-;8675:57;;35670:66:14;8675:57:3;;;35658:79:14;35753:11;;;35746:27;;;35789:12;;;35782:28;;;8639:7:3;;35826:12:14;;8675:57:3;35400:444:14;2243:730:3;2324:7;2333:12;2361:9;:16;2381:2;2361:22;2357:610;;2697:4;2682:20;;2676:27;2746:4;2731:20;;2725:27;2803:4;2788:20;;2782:27;2399:9;2774:36;2844:25;2855:4;2774:36;2676:27;2725;2844:10;:25::i;:::-;2837:32;;;;;;;;;2357:610;-1:-1:-1;2916:1:3;;-1:-1:-1;2920:35:3;2357:610;2243:730;;;;;:::o;21963:1558:7:-;22264:21;;;;22214:7;;22299:31;;;22295:309;;22427:10;;22423:68;;22464:12;;;;;;;;;;;;;;22423:68;22509:4;22505:66;;;22533:23;22541:14;22533:7;:23::i;:::-;22592:1;22585:8;;;;;22295:309;22708:10;;22704:449;;22739:8;:18;;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22734:79;;22786:12;;;;;;;;;;;;;;22734:79;22929:14;22921:5;:22;22917:87;;;22970:19;;;;;;;;;;;;;;22917:87;23123:5;23105:23;;;;22704:449;23167:12;23163:261;;;23200:44;;;;;:15;;;;;;23224:5;;23200:44;;23232:11;;23200:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23195:110;;23271:19;;;;;;;;;;;;;;23195:110;23163:261;;;23326:44;;;;;:15;;;;;;23350:5;;23326:44;;23358:11;;23326:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23321:103;;23393:20;;;;;;;;;;;;;;23321:103;23438:4;23434:58;;;23458:23;23466:14;23458:7;:23::i;:::-;-1:-1:-1;23509:5:7;;21963:1558;-1:-1:-1;;;;;;21963:1558:7:o;27240:415::-;27303:18;;27299:350;;27593:45;27601:10;27623:14;27593:29;:45::i;:::-;27240:415;:::o;5167:1601:3:-;5293:7;;6215:66;6202:79;;6198:161;;;-1:-1:-1;6313:1:3;;-1:-1:-1;6317:30:3;6297:51;;6198:161;6372:1;:7;;6377:2;6372:7;;:18;;;;;6383:1;:7;;6388:2;6383:7;;6372:18;6368:100;;;-1:-1:-1;6422:1:3;;-1:-1:-1;6426:30:3;6406:51;;6368:100;6579:24;;;6562:14;6579:24;;;;;;;;;36076:25:14;;;36149:4;36137:17;;36117:18;;;36110:45;;;;36171:18;;;36164:34;;;36214:18;;;36207:34;;;6579:24:3;;36048:19:14;;6579:24:3;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6579:24:3;;;;;;-1:-1:-1;;6617:20:3;;;6613:101;;6669:1;6673:29;6653:50;;;;;;;6613:101;6732:6;-1:-1:-1;6740:20:3;;-1:-1:-1;5167:1601:3;;;;;;;;:::o;2412:312:1:-;2526:6;2501:21;:31;;2493:73;;;;;;;36454:2:14;2493:73:1;;;36436:21:14;36493:2;36473:18;;;36466:30;36532:31;36512:18;;;36505:59;36581:18;;2493:73:1;;;;;;;;;2578:12;2596:9;:14;;2618:6;2596:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2577:52;;;2647:7;2639:78;;;;;;;37022:2:14;2639:78:1;;;37004:21:14;37061:2;37041:18;;;37034:30;37100:34;37080:18;;;37073:62;37171:28;37151:18;;;37144:56;37217:19;;2639:78:1;36820:422:14;14:407;117:8;127:6;181:3;174:4;166:6;162:17;158:27;148:55;;199:1;196;189:12;148:55;-1:-1:-1;222:20:14;;265:18;254:30;;251:50;;;297:1;294;287:12;251:50;334:4;326:6;322:17;310:29;;394:3;387:4;377:6;374:1;370:14;362:6;358:27;354:38;351:47;348:67;;;411:1;408;401:12;426:528;563:6;571;624:2;612:9;603:7;599:23;595:32;592:52;;;640:1;637;630:12;592:52;680:9;667:23;713:18;705:6;702:30;699:50;;;745:1;742;735:12;699:50;784:110;886:7;877:6;866:9;862:22;784:110;:::i;:::-;913:8;;758:136;;-1:-1:-1;426:528:14;-1:-1:-1;;;;426:528:14:o;1935:250::-;2020:1;2030:113;2044:6;2041:1;2038:13;2030:113;;;2120:11;;;2114:18;2101:11;;;2094:39;2066:2;2059:10;2030:113;;;-1:-1:-1;;2177:1:14;2159:16;;2152:27;1935:250::o;2190:330::-;2232:3;2270:5;2264:12;2297:6;2292:3;2285:19;2313:76;2382:6;2375:4;2370:3;2366:14;2359:4;2352:5;2348:16;2313:76;:::i;:::-;2434:2;2422:15;2439:66;2418:88;2409:98;;;;2509:4;2405:109;;2190:330;-1:-1:-1;;2190:330:14:o;2525:220::-;2674:2;2663:9;2656:21;2637:4;2694:45;2735:2;2724:9;2720:18;2712:6;2694:45;:::i;2750:154::-;2836:42;2829:5;2825:54;2818:5;2815:65;2805:93;;2894:1;2891;2884:12;2909:134;2977:20;;3006:31;2977:20;3006:31;:::i;:::-;2909:134;;;:::o;3048:247::-;3107:6;3160:2;3148:9;3139:7;3135:23;3131:32;3128:52;;;3176:1;3173;3166:12;3128:52;3215:9;3202:23;3234:31;3259:5;3234:31;:::i;3482:407::-;3588:6;3641:2;3629:9;3620:7;3616:23;3612:32;3609:52;;;3657:1;3654;3647:12;3609:52;3697:9;3684:23;3730:18;3722:6;3719:30;3716:50;;;3762:1;3759;3752:12;3716:50;3785:22;;3841:3;3823:16;;;3819:26;3816:46;;;3858:1;3855;3848:12;4419:632;4590:2;4642:21;;;4712:13;;4615:18;;;4734:22;;;4561:4;;4590:2;4813:15;;;;4787:2;4772:18;;;4561:4;4856:169;4870:6;4867:1;4864:13;4856:169;;;4931:13;;4919:26;;5000:15;;;;4965:12;;;;4892:1;4885:9;4856:169;;;-1:-1:-1;5042:3:14;;4419:632;-1:-1:-1;;;;;;4419:632:14:o;5056:203::-;5152:6;5205:2;5193:9;5184:7;5180:23;5176:32;5173:52;;;5221:1;5218;5211:12;5173:52;-1:-1:-1;5244:9:14;5056:203;-1:-1:-1;5056:203:14:o;5788:180::-;5847:6;5900:2;5888:9;5879:7;5875:23;5871:32;5868:52;;;5916:1;5913;5906:12;5868:52;-1:-1:-1;5939:23:14;;5788:180;-1:-1:-1;5788:180:14:o;6920:1102::-;6974:3;7002:6;7035:5;7029:12;7024:3;7017:25;7091:4;7084:5;7080:16;7074:23;7067:4;7062:3;7058:14;7051:47;7144:4;7137:5;7133:16;7127:23;7159:47;7200:4;7195:3;7191:14;7177:12;1699:18;1688:30;1676:43;;1623:102;7159:47;;7254:4;7247:5;7243:16;7237:23;7269:49;7312:4;7307:3;7303:14;7287;1699:18;1688:30;1676:43;;1623:102;7269:49;;7366:4;7359:5;7355:16;7349:23;7381:49;7424:4;7419:3;7415:14;7399;1699:18;1688:30;1676:43;;1623:102;7381:49;;7479:4;7472:5;7468:16;7462:23;7455:4;7450:3;7446:14;7439:47;7534:4;7527:5;7523:16;7517:23;7549:50;7593:4;7588:3;7584:14;7568;6769:42;6758:54;6746:67;;6692:127;7549:50;;7647:4;7640:5;7636:16;7630:23;7662:50;7706:4;7701:3;7697:14;7681;6769:42;6758:54;6746:67;;6692:127;7662:50;-1:-1:-1;7731:6:14;7774:14;;;7768:21;6894:13;6887:21;7830:12;;;6875:34;7862:6;7905:14;;;7899:21;7936:12;;;7929:24;;;7969:47;8003:12;;;7899:21;7969:47;:::i;8027:270::-;8214:2;8203:9;8196:21;8177:4;8234:57;8287:2;8276:9;8272:18;8264:6;8234:57;:::i;8302:213::-;8407:6;8460:3;8448:9;8439:7;8435:23;8431:33;8428:53;;;8477:1;8474;8467:12;8520:315;8588:6;8596;8649:2;8637:9;8628:7;8624:23;8620:32;8617:52;;;8665:1;8662;8655:12;8617:52;8704:9;8691:23;8723:31;8748:5;8723:31;:::i;:::-;8773:5;8825:2;8810:18;;;;8797:32;;-1:-1:-1;;;8520:315:14:o;9287:397::-;9384:6;9437:2;9425:9;9416:7;9412:23;9408:32;9405:52;;;9453:1;9450;9443:12;9405:52;9493:9;9480:23;9526:18;9518:6;9515:30;9512:50;;;9558:1;9555;9548:12;9512:50;9581:22;;9637:2;9619:16;;;9615:25;9612:45;;;9653:1;9650;9643:12;9689:184;9741:77;9738:1;9731:88;9838:4;9835:1;9828:15;9862:4;9859:1;9852:15;9878:407;9995:4;10053:11;10040:25;10143:66;10132:8;10116:14;10112:29;10108:102;10088:18;10084:127;10074:155;;10225:1;10222;10215:12;10074:155;10246:33;;;;;9878:407;-1:-1:-1;;9878:407:14:o;10290:184::-;10342:77;10339:1;10332:88;10439:4;10436:1;10429:15;10463:4;10460:1;10453:15;10479:253;10551:2;10545:9;10593:4;10581:17;;10628:18;10613:34;;10649:22;;;10610:62;10607:88;;;10675:18;;:::i;:::-;10711:2;10704:22;10479:253;:::o;10737:::-;10809:2;10803:9;10851:4;10839:17;;10886:18;10871:34;;10907:22;;;10868:62;10865:88;;;10933:18;;:::i;10995:253::-;11067:2;11061:9;11109:4;11097:17;;11144:18;11129:34;;11165:22;;;11126:62;11123:88;;;11191:18;;:::i;11253:334::-;11324:2;11318:9;11380:2;11370:13;;11385:66;11366:86;11354:99;;11483:18;11468:34;;11504:22;;;11465:62;11462:88;;;11530:18;;:::i;:::-;11566:2;11559:22;11253:334;;-1:-1:-1;11253:334:14:o;11592:204::-;11673:4;11706:18;11698:6;11695:30;11692:56;;;11728:18;;:::i;:::-;-1:-1:-1;11773:1:14;11769:14;11785:4;11765:25;;11592:204::o;11801:490::-;11869:5;11917:4;11905:9;11900:3;11896:19;11892:30;11889:50;;;11935:1;11932;11925:12;11889:50;11968:4;11962:11;12012:4;12004:6;12000:17;12083:6;12071:10;12068:22;12047:18;12035:10;12032:34;12029:62;12026:88;;;12094:18;;:::i;:::-;12130:4;12123:24;12195:23;;12180:39;;12280:2;12265:18;;;12252:32;12235:15;;;12228:57;;;;-1:-1:-1;12165:6:14;11801:490;-1:-1:-1;11801:490:14:o;12296:639::-;12352:5;12400:4;12388:9;12383:3;12379:19;12375:30;12372:50;;;12418:1;12415;12408:12;12372:50;12451:2;12445:9;12493:4;12485:6;12481:17;12564:6;12552:10;12549:22;12528:18;12516:10;12513:34;12510:62;12507:88;;;12575:18;;:::i;:::-;12611:2;12604:22;12644:6;-1:-1:-1;12644:6:14;12674:23;;12741:4;12728:18;;12716:31;;12706:59;;12761:1;12758;12751:12;12706:59;12789:7;12781:6;12774:23;;12858:2;12847:9;12843:18;12830:32;12825:2;12817:6;12813:15;12806:57;12924:2;12913:9;12909:18;12896:32;12891:2;12883:6;12879:15;12872:57;;12296:639;;;;:::o;12940:736::-;13003:5;13056:3;13049:4;13041:6;13037:17;13033:27;13023:55;;13074:1;13071;13064:12;13023:55;13110:6;13097:20;13136:4;13160:81;13176:64;13237:2;13176:64;:::i;:::-;13160:81;:::i;:::-;13275:15;;;13337:4;13380:11;;;13368:24;;13364:33;;;13306:12;;;;13263:3;13409:15;;;13406:35;;;13437:1;13434;13427:12;13406:35;13473:2;13465:6;13461:15;13485:162;13501:6;13496:3;13493:15;13485:162;;;13567:37;13600:3;13595;13567:37;:::i;:::-;13555:50;;13625:12;;;;13518;;13485:162;;;-1:-1:-1;13665:5:14;;12940:736;-1:-1:-1;;;;;;;12940:736:14:o;13681:171::-;13748:20;;13808:18;13797:30;;13787:41;;13777:69;;13842:1;13839;13832:12;13857:1554;14007:9;14066:4;14058:5;14042:14;14038:26;14034:37;14031:57;;;14084:1;14081;14074:12;14031:57;14112:22;;:::i;:::-;14172:5;14159:19;14150:7;14143:36;14198:2;14247;14240:5;14236:14;14223:28;14270:18;14311:2;14303:6;14300:14;14297:34;;;14327:1;14324;14317:12;14297:34;14350:18;;;;14406:14;14399:4;14391:13;;14387:34;14377:62;;14435:1;14432;14425:12;14377:62;14471:2;14458:16;14494:81;14510:64;14571:2;14510:64;:::i;14494:81::-;14609:15;;;14691:1;14687:10;;;;14679:19;;14675:28;;;14640:12;;;;14726:14;14715:26;;14712:46;;;14754:1;14751;14744:12;14712:46;14778:11;;;;14798:187;14814:6;14809:3;14806:15;14798:187;;;14882:60;14927:14;14922:3;14882:60;:::i;:::-;14877:3;14870:73;14972:2;14967:3;14963:12;14956:19;;14840:4;14835:3;14831:14;14824:21;;14798:187;;;15019:5;15014:2;15005:7;15001:16;14994:31;;;;15074:4;15067:5;15063:16;15050:30;15034:46;;15105:2;15095:8;15092:16;15089:36;;;15121:1;15118;15111:12;15089:36;;;15161:75;15221:14;15210:8;15203:5;15199:20;15161:75;:::i;:::-;15154:4;15145:7;15141:18;15134:103;;15271:34;15301:2;15294:5;15290:14;15271:34;:::i;:::-;15266:2;15257:7;15253:16;15246:60;15341:34;15370:3;15363:5;15359:15;15341:34;:::i;:::-;15335:3;15322:17;;15315:61;15326:7;13857:1554;-1:-1:-1;;13857:1554:14:o;15416:184::-;15468:77;15465:1;15458:88;15565:4;15562:1;15555:15;15589:4;15586:1;15579:15;15605:128;15672:9;;;15693:11;;;15690:37;;;15707:18;;:::i;15738:118::-;15824:5;15817:13;15810:21;15803:5;15800:32;15790:60;;15846:1;15843;15836:12;15861:245;15909:4;15942:18;15934:6;15931:30;15928:56;;;15964:18;;:::i;:::-;-1:-1:-1;16021:2:14;16009:15;16026:66;16005:88;16095:4;16001:99;;15861:245::o;16111:1204::-;16180:5;16228:4;16216:9;16211:3;16207:19;16203:30;16200:50;;;16246:1;16243;16236:12;16200:50;16268:22;;:::i;:::-;16259:31;;16327:9;16314:23;16346:33;16371:7;16346:33;:::i;:::-;16388:22;;16429:2;16463:37;16481:18;;;16463:37;:::i;:::-;16458:2;16451:5;16447:14;16440:61;16553:2;16542:9;16538:18;16525:32;16566:30;16588:7;16566:30;:::i;:::-;16623:2;16612:14;;16605:31;16696:2;16681:18;;;16668:32;16652:14;;;16645:56;16752:3;16737:19;;16724:33;16780:18;16769:30;;16766:50;;;16812:1;16809;16802:12;16766:50;16835:22;;16888:4;16880:13;;16876:23;-1:-1:-1;16866:51:14;;16913:1;16910;16903:12;16866:51;16949:2;16936:16;16974:48;16990:31;17018:2;16990:31;:::i;16974:48::-;17045:2;17038:5;17031:17;17085:3;17080:2;17075;17071;17067:11;17063:20;17060:29;17057:49;;;17102:1;17099;17092:12;17057:49;17157:2;17152;17148;17144:11;17139:2;17132:5;17128:14;17115:45;17201:1;17196:2;17191;17184:5;17180:14;17176:23;17169:34;17236:5;17230:3;17223:5;17219:15;17212:30;;;;;17303:3;17292:9;17288:19;17275:33;17269:3;17262:5;17258:15;17251:58;16111:1204;;;;:::o;17320:875::-;17462:9;17521:4;17513:5;17497:14;17493:26;17489:37;17486:57;;;17539:1;17536;17529:12;17486:57;17567:22;;:::i;:::-;17627:5;17614:19;17605:7;17598:36;17681:2;17674:5;17670:14;17657:28;17708:18;17700:6;17697:30;17694:50;;;17740:1;17737;17730:12;17694:50;17778:76;17839:14;17830:6;17823:5;17819:18;17778:76;:::i;:::-;17773:2;17764:7;17760:16;17753:102;;17889:59;17933:14;17928:2;17921:5;17917:14;17889:59;:::i;:::-;17884:2;17875:7;17871:16;17864:85;17997:4;17990:5;17986:16;17973:30;18012:33;18037:7;18012:33;:::i;:::-;18074:4;18061:18;;18054:35;18125:34;18154:3;18143:15;;18125:34;:::i;18200:398::-;18308:4;18366:11;18353:25;18456:66;18445:8;18429:14;18425:29;18421:102;18401:18;18397:127;18387:155;;18538:1;18535;18528:12;18603:238;18735:9;18772:63;18820:14;18813:5;18772:63;:::i;18846:399::-;18955:4;19013:11;19000:25;19103:66;19092:8;19076:14;19072:29;19068:102;19048:18;19044:127;19034:155;;19185:1;19182;19175:12;19250:646;19385:4;19391:6;19451:11;19438:25;19541:66;19530:8;19514:14;19510:29;19506:102;19486:18;19482:127;19472:155;;19623:1;19620;19613:12;19472:155;19650:33;;19702:20;;;-1:-1:-1;19745:18:14;19734:30;;19731:50;;;19777:1;19774;19767:12;19731:50;19810:4;19798:17;;-1:-1:-1;19861:1:14;19857:14;;;19841;19837:35;19827:46;;19824:66;;;19886:1;19883;19876:12;19901:986;20099:9;20134:85;20150:68;20211:6;20150:68;:::i;20134:85::-;20241:3;20265:6;20260:3;20253:19;20291:4;20320:2;20315:3;20311:12;20304:19;;20364:6;20361:1;20357:14;20350:5;20346:26;20395:14;20387:6;20384:26;20381:46;;;20423:1;20420;20413:12;20381:46;20447:5;20461:393;20477:6;20472:3;20469:15;20461:393;;;20563:3;20550:17;20599:18;20586:11;20583:35;20580:125;;;20659:1;20688:2;20684;20677:14;20580:125;20730:81;20796:14;20782:11;20775:5;20771:23;20730:81;:::i;:::-;20718:94;;-1:-1:-1;20832:12:14;;;;20494;;20461:393;;;-1:-1:-1;20876:5:14;;19901:986;-1:-1:-1;;;;;;19901:986:14:o;20892:255::-;20990:6;21043:2;21031:9;21022:7;21018:23;21014:32;21011:52;;;21059:1;21056;21049:12;21011:52;21082:59;21133:7;21122:9;21082:59;:::i;21555:645::-;21689:4;21695:6;21755:11;21742:25;21845:66;21834:8;21818:14;21814:29;21810:102;21790:18;21786:127;21776:155;;21927:1;21924;21917:12;21776:155;21954:33;;22006:20;;;-1:-1:-1;22049:18:14;22038:30;;22035:50;;;22081:1;22078;22071:12;22035:50;22114:4;22102:17;;-1:-1:-1;22165:1:14;22161:14;;;22145;22141:35;22131:46;;22128:66;;;22190:1;22187;22180:12;22871:636;22993:4;22999:6;23059:11;23046:25;23149:66;23138:8;23122:14;23118:29;23114:102;23094:18;23090:127;23080:155;;23231:1;23228;23221:12;23080:155;23258:33;;23310:20;;;-1:-1:-1;23353:18:14;23342:30;;23339:50;;;23385:1;23382;23375:12;23339:50;23418:4;23406:17;;-1:-1:-1;23477:4:14;23465:17;;23449:14;23445:38;23435:49;;23432:69;;;23497:1;23494;23487:12;23512:231;23598:6;23651:2;23639:9;23630:7;23626:23;23622:32;23619:52;;;23667:1;23664;23657:12;23619:52;23690:47;23729:7;23718:9;23690:47;:::i;23748:184::-;23806:6;23859:2;23847:9;23838:7;23834:23;23830:32;23827:52;;;23875:1;23872;23865:12;23827:52;23898:28;23916:9;23898:28;:::i;23937:437::-;24016:1;24012:12;;;;24059;;;24080:61;;24134:4;24126:6;24122:17;24112:27;;24080:61;24187:2;24179:6;24176:14;24156:18;24153:38;24150:218;;24224:77;24221:1;24214:88;24325:4;24322:1;24315:15;24353:4;24350:1;24343:15;24379:702;24482:6;24535:3;24523:9;24514:7;24510:23;24506:33;24503:53;;;24552:1;24549;24542:12;24503:53;24578:22;;:::i;:::-;24636:9;24623:23;24616:5;24609:38;24679:68;24739:7;24734:2;24723:9;24719:18;24679:68;:::i;:::-;24674:2;24667:5;24663:14;24656:92;24782:56;24830:7;24825:2;24814:9;24810:18;24782:56;:::i;:::-;24775:4;24768:5;24764:16;24757:82;24891:3;24880:9;24876:19;24863:33;24905;24930:7;24905:33;:::i;:::-;24965:2;24954:14;;24947:31;25012:38;25045:3;25030:19;;25012:38;:::i;:::-;25005:4;24994:16;;24987:64;24998:5;24379:702;-1:-1:-1;;;24379:702:14:o;25086:195::-;25125:3;25156:66;25149:5;25146:77;25143:103;;25226:18;;:::i;:::-;-1:-1:-1;25273:1:14;25262:13;;25086:195::o;26366:1250::-;26466:6;26497:2;26540;26528:9;26519:7;26515:23;26511:32;26508:52;;;26556:1;26553;26546:12;26508:52;26589:9;26583:16;26618:18;26659:2;26651:6;26648:14;26645:34;;;26675:1;26672;26665:12;26645:34;26698:22;;;;26754:4;26736:16;;;26732:27;26729:47;;;26772:1;26769;26762:12;26729:47;26798:22;;:::i;:::-;26849:2;26843:9;26836:5;26829:24;26891:2;26887;26883:11;26877:18;26904:33;26929:7;26904:33;:::i;:::-;26953:14;;;26946:31;27015:2;27007:11;;27001:18;27028:30;27001:18;27028:30;:::i;:::-;27085:2;27074:14;;27067:31;27137:2;27129:11;;27123:18;27153:16;;;27150:36;;;27182:1;27179;27172:12;27150:36;27213:8;27209:2;27205:17;27195:27;;;27260:7;27253:4;27249:2;27245:13;27241:27;27231:55;;27282:1;27279;27272:12;27231:55;27311:2;27305:9;27295:19;;27336:48;27352:31;27380:2;27352:31;:::i;27336:48::-;27407:2;27400:5;27393:17;27447:7;27442:2;27437;27433;27429:11;27425:20;27422:33;27419:53;;;27468:1;27465;27458:12;27419:53;27481:67;27545:2;27540;27533:5;27529:14;27524:2;27520;27516:11;27481:67;:::i;:::-;27575:2;27564:14;;27557:29;27568:5;26366:1250;-1:-1:-1;;;;;;26366:1250:14:o;28788:544::-;28889:2;28884:3;28881:11;28878:448;;;28925:1;28950:5;28946:2;28939:17;28995:4;28991:2;28981:19;29065:2;29053:10;29049:19;29046:1;29042:27;29036:4;29032:38;29101:4;29089:10;29086:20;29083:47;;;-1:-1:-1;29124:4:14;29083:47;29179:2;29174:3;29170:12;29167:1;29163:20;29157:4;29153:31;29143:41;;29234:82;29252:2;29245:5;29242:13;29234:82;;;29297:17;;;29278:1;29267:13;29234:82;;;29238:3;;;28788:544;;;:::o;29568:1467::-;29692:3;29686:10;29719:18;29711:6;29708:30;29705:56;;;29741:18;;:::i;:::-;29770:96;29859:6;29819:38;29851:4;29845:11;29819:38;:::i;:::-;29813:4;29770:96;:::i;:::-;29921:4;;29985:2;29974:14;;30002:1;29997:781;;;;30822:1;30839:6;30836:89;;;-1:-1:-1;30891:19:14;;;30885:26;30836:89;29474:66;29465:1;29461:11;;;29457:84;29453:89;29443:100;29549:1;29545:11;;;29440:117;30938:81;;29967:1062;;29997:781;28735:1;28728:14;;;28772:4;28759:18;;30045:66;30033:79;;;30209:236;30223:7;30220:1;30217:14;30209:236;;;30312:19;;;30306:26;30291:42;;30404:27;;;;30372:1;30360:14;;;;30239:19;;30209:236;;;30213:3;30473:6;30464:7;30461:19;30458:261;;;30534:19;;;30528:26;30635:66;30617:1;30613:14;;;30629:3;30609:24;30605:97;30601:102;30586:118;30571:134;;30458:261;-1:-1:-1;;;;;30765:1:14;30749:14;;;30745:22;30732:36;;-1:-1:-1;29568:1467:14:o;31040:184::-;31092:77;31089:1;31082:88;31189:4;31186:1;31179:15;31213:4;31210:1;31203:15;31229:289;31404:6;31393:9;31386:25;31447:2;31442;31431:9;31427:18;31420:30;31367:4;31467:45;31508:2;31497:9;31493:18;31485:6;31467:45;:::i;:::-;31459:53;31229:289;-1:-1:-1;;;;31229:289:14:o;31523:287::-;31652:3;31690:6;31684:13;31706:66;31765:6;31760:3;31753:4;31745:6;31741:17;31706:66;:::i;31815:184::-;31885:6;31938:2;31926:9;31917:7;31913:23;31909:32;31906:52;;;31954:1;31951;31944:12;31906:52;-1:-1:-1;31977:16:14;;31815:184;-1:-1:-1;31815:184:14:o;32004:245::-;32071:6;32124:2;32112:9;32103:7;32099:23;32095:32;32092:52;;;32140:1;32137;32130:12;32092:52;32172:9;32166:16;32191:28;32213:5;32191:28;:::i;32254:1441::-;32532:4;32580:2;32569:9;32565:18;32610:2;32599:9;32592:21;32633:6;32668;32662:13;32699:6;32691;32684:22;32737:2;32726:9;32722:18;32715:25;;32799:2;32789:6;32786:1;32782:14;32771:9;32767:30;32763:39;32749:53;;32821:4;32860:2;32852:6;32848:15;32881:1;32891:326;32905:6;32902:1;32899:13;32891:326;;;32994:66;32982:9;32974:6;32970:22;32966:95;32961:3;32954:108;33085:52;33130:6;33121;33115:13;33085:52;:::i;:::-;33075:62;-1:-1:-1;33195:12:14;;;;33160:15;;;;32927:1;32920:9;32891:326;;;-1:-1:-1;;33253:22:14;;;33233:18;;;33226:50;33329:13;;33351:24;;;33433:15;;;;33393;;;-1:-1:-1;33329:13:14;-1:-1:-1;33468:1:14;33478:189;33494:8;33489:3;33486:17;33478:189;;;33563:15;;33549:30;;33640:17;;;;33601:14;;;;33522:1;33513:11;33478:189;;;-1:-1:-1;33684:5:14;;32254:1441;-1:-1:-1;;;;;;;32254:1441:14:o;33700:1178::-;34071:6;34066:3;34059:19;34041:3;34097:66;34214:2;34205:6;34201:2;34197:15;34193:24;34188:2;34183:3;34179:12;34172:46;34269:2;34260:6;34256:2;34252:15;34248:24;34243:2;34238:3;34234:12;34227:46;;34292:66;34410:2;34401:6;34396:3;34392:16;34388:25;34383:2;34378:3;34374:12;34367:47;34466:2;34457:6;34452:3;34448:16;34444:25;34439:2;34434:3;34430:12;34423:47;;34523:6;34516:14;34509:22;34504:3;34500:32;34495:2;34490:3;34486:12;34479:54;34563:6;34558:2;34553:3;34549:12;34542:28;34599:6;34593:13;34615:74;34682:6;34676:3;34671;34667:13;34662:2;34654:6;34650:15;34615:74;:::i;:::-;34717:6;34712:3;34708:16;34698:26;;34776:66;34767:6;34762:3;34758:16;34754:89;34748:3;34744:2;34740:12;34733:111;34868:3;34864:2;34860:12;34853:19;;;33700:1178;;;;;;;;;;;;:::o
Swarm Source
none
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.