Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 12 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 16850894 | 319 days ago | 0 ETH | ||||
| 13431450 | 404 days ago | 0 ETH | ||||
| 8726255 | 515 days ago | 0 ETH | ||||
| 1953620 | 726 days ago | 0 ETH | ||||
| 1953486 | 726 days ago | 0 ETH | ||||
| 1953485 | 726 days ago | 0 ETH | ||||
| 1953485 | 726 days ago | 0 ETH | ||||
| 1953485 | 726 days ago | 0 ETH | ||||
| 1953485 | 726 days ago | 0 ETH | ||||
| 1953485 | 726 days ago | 0 ETH | ||||
| 1953483 | 726 days ago | 0 ETH | ||||
| 1953400 | 726 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
GitcoinPassportDecoder
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.9;
import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {Attestation, IEAS} from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
import {IGitcoinResolver} from "./IGitcoinResolver.sol";
import {Credential, IGitcoinPassportDecoder} from "./IGitcoinPassportDecoder.sol";
/**
* @title GitcoinPassportDecoder
* @notice This contract is used to create the bit map of stamp providers onchain, which will allow us to score Passports fully onchain
*/
contract GitcoinPassportDecoder is
IGitcoinPassportDecoder,
Initializable,
UUPSUpgradeable,
OwnableUpgradeable,
PausableUpgradeable
{
// The instance of the EAS contract.
IEAS public eas;
// Mapping of the current version to provider arrays
mapping(uint32 => string[]) public providerVersions;
// Mapping of previously stored providers
mapping(uint32 => mapping(string => uint8)) public reversedMappingVersions;
// Current version number
uint32 public currentVersion;
// Instance of the GitcoinResolver contract
IGitcoinResolver public gitcoinResolver;
// Passport attestation schema UID
bytes32 public passportSchemaUID;
// Score attestation schema UID
bytes32 public scoreSchemaUID;
// Maximum score age in seconds
uint64 public maxScoreAge;
// Minimum score
uint256 public threshold;
/// A provider with the same name already exists
/// @param provider the name of the duplicate provider
error ProviderAlreadyExists(string provider);
/// An empty provider string was passed
error EmptyProvider();
/// Zero value was passed
error ZeroValue();
/// An attestation for the specified ETH address does not exist within the GitcoinResolver
error AttestationNotFound();
/// An attestation was found but it is expired
/// @param expirationTime the expiration time of the attestation
error AttestationExpired(uint64 expirationTime);
/// A threshold of zero was passed
error ZeroThreshold();
/// A max score age of zero was passed
error ZeroMaxScoreAge();
/// Score does not meet the threshold
error ScoreDoesNotMeetThreshold(uint256 score);
// Events
event EASSet(address easAddress);
event ResolverSet(address resolverAddress);
event SchemaSet(bytes32 schemaUID);
event ProvidersAdded(string[] providers);
event NewVersionCreated();
event MaxScoreAgeSet(uint256 maxScoreAge);
event ThresholdSet(uint256 threshold);
function initialize() public initializer {
__Ownable_init();
__Pausable_init();
_initCurrentVersion(new string[](0));
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function _authorizeUpgrade(address) internal override onlyOwner {}
/**
* @dev Gets providers by version.
*/
function getProviders(uint32 version) public view returns (string[] memory) {
return providerVersions[version];
}
/**
* @dev Sets the address of the EAS contract.
* @param _easContractAddress The address of the EAS contract.
*/
function setEASAddress(address _easContractAddress) external onlyOwner {
if (_easContractAddress == address(0)) {
revert ZeroValue();
}
eas = IEAS(_easContractAddress);
emit EASSet(_easContractAddress);
}
/**
* @dev Sets the GitcoinResolver contract.
* @param _gitcoinResolver The address of the GitcoinResolver contract.
*/
function setGitcoinResolver(address _gitcoinResolver) external onlyOwner {
if (_gitcoinResolver == address(0)) {
revert ZeroValue();
}
gitcoinResolver = IGitcoinResolver(_gitcoinResolver);
emit ResolverSet(_gitcoinResolver);
}
/**
* @dev Sets the schemaUID for the Passport Attestation.
* @param _schemaUID The UID of the schema used to make the user's passport attestation
*/
function setPassportSchemaUID(bytes32 _schemaUID) public onlyOwner {
if (_schemaUID == bytes32(0)) {
revert ZeroValue();
}
passportSchemaUID = _schemaUID;
emit SchemaSet(_schemaUID);
}
/**
* @dev Sets the schemaUID for the Score Attestation.
* @param _schemaUID The UID of the schema used to make the user's score attestation
*/
function setScoreSchemaUID(bytes32 _schemaUID) public onlyOwner {
if (_schemaUID == bytes32(0)) {
revert ZeroValue();
}
scoreSchemaUID = _schemaUID;
emit SchemaSet(_schemaUID);
}
/**
* @dev Sets the maximum allowed age of the score
* @param _maxScoreAge Max age of the score in seconds
*/
function setMaxScoreAge(uint64 _maxScoreAge) public onlyOwner {
if (_maxScoreAge == 0) {
revert ZeroMaxScoreAge();
}
maxScoreAge = _maxScoreAge;
emit MaxScoreAgeSet(maxScoreAge);
}
/**
* @dev Sets the threshold for the minimum score
* @param _threshold Minimum score allowed, as a 4 digit number
*/
function setThreshold(uint256 _threshold) public onlyOwner {
if (_threshold == 0) {
revert ZeroThreshold();
}
threshold = _threshold;
emit ThresholdSet(threshold);
}
/**
* @dev Adds a new provider to the end of the providerVersions mapping
* @param providers provider name
*/
function addProviders(string[] memory providers) external onlyOwner {
for (uint256 i = 0; i < providers.length; ) {
if (bytes(providers[i]).length == 0) {
revert EmptyProvider();
}
if (reversedMappingVersions[currentVersion][providers[i]] == 1) {
revert ProviderAlreadyExists(providers[i]);
}
providerVersions[currentVersion].push(providers[i]);
reversedMappingVersions[currentVersion][providers[i]] = 1;
unchecked {
++i;
}
}
emit ProvidersAdded(providers);
}
/**
* @dev Creates a new provider.
* @param providers Array of provider names
*/
function _initCurrentVersion(string[] memory providers) internal {
for (uint256 i = 0; i < providers.length; ) {
if (bytes(providers[i]).length == 0) {
revert EmptyProvider();
}
unchecked {
++i;
}
}
providerVersions[currentVersion] = providers;
}
/**
* @dev Creates a new provider.
* @param providers Array of provider names
*/
function createNewVersion(string[] memory providers) external onlyOwner {
currentVersion++;
_initCurrentVersion(providers);
emit NewVersionCreated();
}
/**
* Return an attestation for a given UID
* @param attestationUID The UID of the attestation
*/
function getAttestation(
bytes32 attestationUID
) public view returns (Attestation memory) {
Attestation memory attestation = eas.getAttestation(attestationUID);
return attestation;
}
/**
* @dev Retrieves the user's Passport attestation via the GitcoinResolver and IEAS and decodes the bits in the provider map to output a readable Passport
* @param user User's address
*/
function getPassport(
address user
) external view returns (Credential[] memory) {
// Get the attestation UID from the user's attestations
bytes32 attestationUID = gitcoinResolver.getUserAttestation(
user,
passportSchemaUID
);
// Check if the attestation UID exists within the GitcoinResolver. When an attestation is revoked that attestation UID is set to 0.
if (attestationUID == 0) {
revert AttestationNotFound();
}
// Get the attestation from the user's attestation UID
Attestation memory attestation = getAttestation(attestationUID);
// Check for expiration time
if (
attestation.expirationTime > 0 &&
attestation.expirationTime <= block.timestamp
) {
revert AttestationExpired(attestation.expirationTime);
}
// Set up the variables to assign the attestion data output to
uint256[] memory providers;
bytes32[] memory hashes;
uint64[] memory issuanceDates;
uint64[] memory expirationDates;
uint16 providerMapVersion;
// Decode the attestion output
(
providers,
hashes,
issuanceDates,
expirationDates,
providerMapVersion
) = abi.decode(
attestation.data,
(uint256[], bytes32[], uint64[], uint64[], uint16)
);
// Set up the variables to record the bit and the index of the credential hash
uint256 bit;
uint256 hashIndex = 0;
// Set the list of providers to the provider map version
string[] memory mappedProviders = providerVersions[providerMapVersion];
uint256 hashLength = uint256(hashes.length);
uint256 providersBucketsLength = uint256(providers.length);
uint256 mappedProvidersLength = uint256(mappedProviders.length);
// Check to make sure that the lengths of the hashes, issuanceDates, and expirationDates match, otherwise end the function call
assert(
hashLength == issuanceDates.length && hashLength == expirationDates.length
);
// Set the in-memory passport array to be returned to equal the length of the hashes array
Credential[] memory passportMemoryArray = new Credential[](hashLength);
// Now we iterate over the providers array and check each bit that is set
// If a bit is set
// we set the hash, issuanceDate, expirationDate, and provider to a Credential struct
// then we push that struct to the passport storage array and populate the passportMemoryArray
for (uint256 i = 0; i < providersBucketsLength; ) {
bit = 1;
uint256 provider = uint256(providers[i]);
for (uint256 j = 0; j < 256; ) {
// Check to make sure that the hashIndex is less than the length of the expirationDates array, and if not, exit the loop
if (hashIndex >= hashLength) {
break;
}
uint256 mappedProvidersIndex = i * 256 + j;
if (mappedProvidersIndex > mappedProvidersLength) {
break;
}
// Check that the provider bit is set
// The provider bit is set --> set the provider, hash, issuance date, and expiration date to the struct
if (provider & bit > 0) {
Credential memory credential;
// Set provider to the credential struct from the mappedProviders mapping
credential.provider = mappedProviders[mappedProvidersIndex];
// Set the hash to the credential struct from the hashes array
credential.hash = hashes[hashIndex];
// Set the issuanceDate of the credential struct to the item at the current index of the issuanceDates array
credential.time = issuanceDates[hashIndex];
// Set the expirationDate of the credential struct to the item at the current index of the expirationDates array
credential.expirationTime = expirationDates[hashIndex];
// Set the hashIndex with the finished credential struct
passportMemoryArray[hashIndex] = credential;
hashIndex += 1;
}
unchecked {
bit <<= 1;
++j;
}
}
unchecked {
i += 256;
}
}
// Return the memory passport array
return passportMemoryArray;
}
/**
* This function will check a score attestation for expiration.
* Even though the score attestation does not have an expiry date, ths function will check
* that it is not older than `maxScoreAge` seconds since issuance.
*
* @param attestation The attestation to check for expiration
*/
function _isScoreAttestationExpired(
Attestation memory attestation
) internal view returns (bool) {
if (attestation.expirationTime > 0) {
return block.timestamp > attestation.expirationTime;
}
return block.timestamp > attestation.time + maxScoreAge;
}
/**
* This function will check a cached score for expiration (this is the equivalent
* of the `_isScoreAttestationExpired` function for cached scores)
*
* @param score The attestation to check for expiration
*/
function _isCachedScoreExpired(
IGitcoinResolver.CachedScore memory score
) internal view returns (bool) {
if (score.expirationTime > 0) {
// If the score has an expiration time, check that it is not expired
return block.timestamp > score.expirationTime;
}
return (block.timestamp > score.time + maxScoreAge);
}
/**
* @dev Retrieves the user's Score attestation via the GitcoinResolver and returns it as a 4 digit number
* @param user The ETH address of the recipient
*/
function getScore(address user) public view returns (uint256) {
IGitcoinResolver.CachedScore memory cachedScore = gitcoinResolver
.getCachedScore(user);
if (cachedScore.time != 0) {
// Check for expiration time
if (_isCachedScoreExpired(cachedScore)) {
revert AttestationExpired(cachedScore.time);
}
// Return the score value
return cachedScore.score;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Fallback: read the score from the attestation if retreiving it from the cache eas not possible
//////////////////////////////////////////////////////////////////////////////////////////////////
bytes32 attestationUID = gitcoinResolver.getUserAttestation(
user,
scoreSchemaUID
);
// Check if the attestation UID exists within the GitcoinResolver. When an attestation is revoked that attestation UID is set to 0.
if (attestationUID == 0) {
revert AttestationNotFound();
}
// Get the attestation from the user's attestation UID
Attestation memory attestation = getAttestation(attestationUID);
// Decode the attestion output
uint256 score;
uint8 decimals;
(score, , decimals) = abi.decode(
attestation.data,
(uint256, uint32, uint8)
);
// Convert the number to a 4 digit number
if (decimals > 4) {
score /= 10 ** (decimals - 4);
} else if (decimals < 4) {
score *= 10 ** (4 - decimals);
}
// Check if score is older than max age
if (_isScoreAttestationExpired(attestation)) {
revert AttestationExpired(attestation.time + maxScoreAge);
}
// Return the score value
return score;
}
/**
* @dev Determines if a user is a human based on their score being above a certain threshold and valid within the max score age
* @param user The ETH address of the recipient
*/
function isHuman(address user) public view returns (bool) {
uint256 score = getScore(user);
return score >= threshold;
}
}// 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();
/// @notice 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.
}
/// @notice 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.
}
/// @notice A helper function to work with unchecked iterators in loops.
function uncheckedInc(uint256 i) pure returns (uint256 j) {
unchecked {
j = i + 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { Attestation, Signature } from "./Common.sol";
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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.
}
/// @notice 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 EAS - Ethereum Attestation Service interface.
interface IEAS {
/// @notice 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);
/// @notice 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);
/// @notice Emitted when a data has been timestamped.
/// @param data The data.
/// @param timestamp The timestamp.
event Timestamped(bytes32 indexed data, uint64 indexed timestamp);
/// @notice 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.
/// @param request The arguments of the attestation request.
/// @return The UID of the new attestation.
///
/// Example:
/// attest({
/// schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
/// data: {
/// recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
/// expirationTime: 0,
/// revocable: true,
/// refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
/// data: "0xF00D",
/// value: 0
/// }
/// })
function attest(AttestationRequest calldata request) external payable returns (bytes32);
/// @notice Attests to a specific schema via the provided ECDSA signature.
/// @param delegatedRequest The arguments of the delegated attestation request.
/// @return The UID of the new attestation.
///
/// 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
/// })
function attestByDelegation(
DelegatedAttestationRequest calldata delegatedRequest
) external payable returns (bytes32);
/// @notice Attests to multiple schemas.
/// @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.
///
/// 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
/// },
/// }])
function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory);
/// @notice Attests to multiple schemas using via provided ECDSA signatures.
/// @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.
///
/// 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
/// }])
function multiAttestByDelegation(
MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
) external payable returns (bytes32[] memory);
/// @notice Revokes an existing attestation to a specific schema.
/// @param request The arguments of the revocation request.
///
/// Example:
/// revoke({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
/// value: 0
/// }
/// })
function revoke(RevocationRequest calldata request) external payable;
/// @notice Revokes an existing attestation to a specific schema via the provided ECDSA signature.
/// @param delegatedRequest The arguments of the delegated revocation request.
///
/// Example:
/// revokeByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
/// value: 0
/// },
/// signature: {
/// v: 27,
/// r: '0xb593...7142',
/// s: '0x0f5b...2cce'
/// },
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
/// deadline: 1673891048
/// })
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;
/// @notice Revokes existing attestations to multiple schemas.
/// @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.
///
/// Example:
/// multiRevoke([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
/// value: 0
/// },
/// }])
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;
/// @notice Revokes existing attestations to multiple schemas via provided ECDSA signatures.
/// @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.
///
/// 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
/// }])
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 "./resolver/ISchemaResolver.sol";
/// @notice 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 {
/// @notice 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);
/// @notice 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);
/// @notice 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.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
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: GPL
pragma solidity ^0.8.9;
/**
* @dev A struct storing a passpor credential
*/
struct Credential {
string provider;
bytes32 hash;
uint64 time;
uint64 expirationTime;
}
/**
* @title IGitcoinPassportDecoder
* @notice Minimal interface for consuming GitcoinPassportDecoder data
*/
interface IGitcoinPassportDecoder {
function getPassport(
address user
) external returns (Credential[] memory);
function getScore(address user) external view returns (uint256);
function isHuman(address user) external view returns (bool);
}// SPDX-License-Identifier: GPL
pragma solidity ^0.8.9;
/**
* @title IGitcoinResolver
* @notice Minimal interface for consuming GitcoinResolver data
*/
interface IGitcoinResolver {
// Cached data structure
// Stores a score in a 32 byte data structure for efficient access when reading
struct CachedScore {
uint32 score; // compacted uint value 4 decimal places
uint64 time; // For checking the age of the stamp, without loading the attestation
uint64 expirationTime; // This makes sense because we want to make sure the stamp is not expired, and also do not want to load the attestation
}
/**
*
* @param user The ETH address of the recipient
* @param schema THE UID of the chema
* @return The attestation UID or 0x0 if not found
*/
function getUserAttestation(
address user,
bytes32 schema
) external view returns (bytes32);
/**
*
* @param user The ETH address of the recipient
* @return The `CachedScore` for the given ETH address.
* A non-zero value in the `issuanceDate` indicates that a valid score has been retreived.
*/
function getCachedScore(
address user
) external view returns (CachedScore memory);
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint64","name":"expirationTime","type":"uint64"}],"name":"AttestationExpired","type":"error"},{"inputs":[],"name":"AttestationNotFound","type":"error"},{"inputs":[],"name":"EmptyProvider","type":"error"},{"inputs":[{"internalType":"string","name":"provider","type":"string"}],"name":"ProviderAlreadyExists","type":"error"},{"inputs":[{"internalType":"uint256","name":"score","type":"uint256"}],"name":"ScoreDoesNotMeetThreshold","type":"error"},{"inputs":[],"name":"ZeroMaxScoreAge","type":"error"},{"inputs":[],"name":"ZeroThreshold","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"easAddress","type":"address"}],"name":"EASSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxScoreAge","type":"uint256"}],"name":"MaxScoreAgeSet","type":"event"},{"anonymous":false,"inputs":[],"name":"NewVersionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string[]","name":"providers","type":"string[]"}],"name":"ProvidersAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"resolverAddress","type":"address"}],"name":"ResolverSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"schemaUID","type":"bytes32"}],"name":"SchemaSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"ThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"string[]","name":"providers","type":"string[]"}],"name":"addProviders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"providers","type":"string[]"}],"name":"createNewVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentVersion","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eas","outputs":[{"internalType":"contract IEAS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"attestationUID","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":[{"internalType":"address","name":"user","type":"address"}],"name":"getPassport","outputs":[{"components":[{"internalType":"string","name":"provider","type":"string"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"}],"internalType":"struct Credential[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"version","type":"uint32"}],"name":"getProviders","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getScore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gitcoinResolver","outputs":[{"internalType":"contract IGitcoinResolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isHuman","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxScoreAge","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passportSchemaUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"providerVersions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"string","name":"","type":"string"}],"name":"reversedMappingVersions","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scoreSchemaUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_easContractAddress","type":"address"}],"name":"setEASAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gitcoinResolver","type":"address"}],"name":"setGitcoinResolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxScoreAge","type":"uint64"}],"name":"setMaxScoreAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_schemaUID","type":"bytes32"}],"name":"setPassportSchemaUID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_schemaUID","type":"bytes32"}],"name":"setScoreSchemaUID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"threshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
60a06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff1681525034801561004357600080fd5b50608051614ee561007b600039600081816108f70152818161098501528181610e9401528181610f220152610fd20152614ee56000f3fe6080604052600436106101e35760003560e01c80638456cb5911610102578063bb169f7f11610095578063d47875d011610064578063d47875d014610687578063e4a59209146106c4578063f2fde38b146106ed578063f72c436f14610716576101e3565b8063bb169f7f146105df578063c82bfbb714610608578063ceab398814610633578063d2ae372c1461065e576101e3565b8063960bfe04116100d1578063960bfe04146105255780639d888e861461054e578063a3112a6414610579578063a46767b5146105b6576101e3565b80638456cb591461047b57806386b69e8a146104925780638da5cb5b146104cf57806391c70059146104fa576101e3565b80634f1ef2861161017a5780635e33ef5d116101495780635e33ef5d146103f7578063715018a6146104225780638129fc1c146104395780638150864d14610450576101e3565b80634f1ef2861461034857806352d1902d1461036457806357a5893c1461038f5780635c975abb146103cc576101e3565b80633f4ba83a116101b65780633f4ba83a146102a0578063420b7589146102b757806342cde4e8146102e05780634e62cf3f1461030b576101e3565b80631cd191e8146101e85780632e314f65146102255780633659cfe61461024e5780633923d3ef14610277575b600080fd5b3480156101f457600080fd5b5061020f600480360381019061020a9190612c83565b610753565b60405161021c9190612d53565b60405180910390f35b34801561023157600080fd5b5061024c60048036038101906102479190612dd3565b61080c565b005b34801561025a57600080fd5b5061027560048036038101906102709190612dd3565b6108f5565b005b34801561028357600080fd5b5061029e6004803603810190610299919061301b565b610a7d565b005b3480156102ac57600080fd5b506102b5610afe565b005b3480156102c357600080fd5b506102de60048036038101906102d9919061301b565b610b10565b005b3480156102ec57600080fd5b506102f5610d94565b6040516103029190613073565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d919061308e565b610d9a565b60405161033f91906131c7565b60405180910390f35b610362600480360381019061035d919061328a565b610e92565b005b34801561037057600080fd5b50610379610fce565b60405161038691906132ff565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190612dd3565b611087565b6040516103c39190613471565b60405180910390f35b3480156103d857600080fd5b506103e1611540565b6040516103ee91906134ae565b60405180910390f35b34801561040357600080fd5b5061040c611557565b6040516104199190613528565b60405180910390f35b34801561042e57600080fd5b5061043761157d565b005b34801561044557600080fd5b5061044e611591565b005b34801561045c57600080fd5b5061046561172e565b6040516104729190613564565b60405180910390f35b34801561048757600080fd5b50610490611754565b005b34801561049e57600080fd5b506104b960048036038101906104b4919061357f565b611766565b6040516104c691906135f7565b60405180910390f35b3480156104db57600080fd5b506104e46117ab565b6040516104f19190613621565b60405180910390f35b34801561050657600080fd5b5061050f6117d5565b60405161051c91906132ff565b60405180910390f35b34801561053157600080fd5b5061054c6004803603810190610547919061363c565b6117db565b005b34801561055a57600080fd5b50610563611860565b6040516105709190613678565b60405180910390f35b34801561058557600080fd5b506105a0600480360381019061059b91906136bf565b611876565b6040516105ad9190613839565b60405180910390f35b3480156105c257600080fd5b506105dd60048036038101906105d891906136bf565b61192c565b005b3480156105eb57600080fd5b50610606600480360381019061060191906136bf565b6119b1565b005b34801561061457600080fd5b5061061d611a36565b60405161062a919061386a565b60405180910390f35b34801561063f57600080fd5b50610648611a50565b60405161065591906132ff565b60405180910390f35b34801561066a57600080fd5b5061068560048036038101906106809190612dd3565b611a56565b005b34801561069357600080fd5b506106ae60048036038101906106a99190612dd3565b611b3f565b6040516106bb9190613073565b60405180910390f35b3480156106d057600080fd5b506106eb60048036038101906106e691906138b1565b611e54565b005b3480156106f957600080fd5b50610714600480360381019061070f9190612dd3565b611f19565b005b34801561072257600080fd5b5061073d60048036038101906107389190612dd3565b611f9c565b60405161074a91906134ae565b60405180910390f35b6098602052816000526040600020818154811061076f57600080fd5b9060005260206000200160009150915050805461078b9061390d565b80601f01602080910402602001604051908101604052809291908181526020018280546107b79061390d565b80156108045780601f106107d957610100808354040283529160200191610804565b820191906000526020600020905b8154815290600101906020018083116107e757829003601f168201915b505050505081565b610814611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361087a576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609a60046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f14dc79d338b451b8b7b20e3191752ac97cbc8b011ff3b921597b83b1222896ae816040516108ea9190613621565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1603610983576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097a906139b0565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166109c2612036565b73ffffffffffffffffffffffffffffffffffffffff1614610a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0f90613a42565b60405180910390fd5b610a218161208d565b610a7a81600067ffffffffffffffff811115610a4057610a3f612e05565b5b6040519080825280601f01601f191660200182016040528015610a725781602001600182028036833780820191505090505b506000612098565b50565b610a85611fb8565b609a600081819054906101000a900463ffffffff1680929190610aa790613a91565b91906101000a81548163ffffffff021916908363ffffffff16021790555050610acf81612206565b7f4e210ed25abf187b8a2f6c516deef88d958c75e285b05928d7db0f8a673ce25f60405160405180910390a150565b610b06611fb8565b610b0e6122bc565b565b610b18611fb8565b60005b8151811015610d59576000828281518110610b3957610b38613abd565b5b60200260200101515103610b79576040517f88998c5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160996000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020838381518110610bbf57610bbe613abd565b5b6020026020010151604051610bd49190613b28565b908152602001604051809103902060009054906101000a900460ff1660ff1603610c4f57818181518110610c0b57610c0a613abd565b5b60200260200101516040517fee118ba6000000000000000000000000000000000000000000000000000000008152600401610c469190612d53565b60405180910390fd5b60986000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020828281518110610c9357610c92613abd565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509081610ccc9190613ce1565b50600160996000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020838381518110610d1357610d12613abd565b5b6020026020010151604051610d289190613b28565b908152602001604051809103902060006101000a81548160ff021916908360ff160217905550806001019050610b1b565b507fec76e5d73810a27d70d44fe10dd9040c9c446187c33df2ae02ceb4b07cfa7eb781604051610d8991906131c7565b60405180910390a150565b609e5481565b6060609860008363ffffffff1663ffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610e87578382906000526020600020018054610dfa9061390d565b80601f0160208091040260200160405190810160405280929190818152602001828054610e269061390d565b8015610e735780601f10610e4857610100808354040283529160200191610e73565b820191906000526020600020905b815481529060010190602001808311610e5657829003601f168201915b505050505081526020019060010190610ddb565b505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1603610f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f17906139b0565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610f5f612036565b73ffffffffffffffffffffffffffffffffffffffff1614610fb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fac90613a42565b60405180910390fd5b610fbe8261208d565b610fca82826001612098565b5050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161461105e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105590613e25565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905090565b60606000609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379300e5684609b546040518363ffffffff1660e01b81526004016110ea929190613e45565b602060405180830381865afa158015611107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112b9190613e83565b90506000801b8103611169576040517f120a2e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061117482611876565b90506000816060015167ffffffffffffffff161180156111a2575042816060015167ffffffffffffffff1611155b156111e85780606001516040517f06c094050000000000000000000000000000000000000000000000000000000081526004016111df919061386a565b60405180910390fd5b6060806060806000856101200151806020019051810190611209919061415d565b8095508196508297508398508499505050505050600080600090506000609860008561ffff1663ffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561130f5783829060005260206000200180546112829061390d565b80601f01602080910402602001604051908101604052809291908181526020018280546112ae9061390d565b80156112fb5780601f106112d0576101008083540402835291602001916112fb565b820191906000526020600020905b8154815290600101906020018083116112de57829003601f168201915b505050505081526020019060010190611263565b5050505090506000875190506000895190506000835190508851831480156113375750875183145b61134457611343614248565b5b60008367ffffffffffffffff8111156113605761135f612e05565b5b60405190808252806020026020018201604052801561139957816020015b611386612a3c565b81526020019060019003908161137e5790505b50905060005b83811015611529576001975060008d82815181106113c0576113bf613abd565b5b6020026020010151905060005b61010081101561151b578689101561151b57600081610100856113f09190614277565b6113fa91906142b9565b90508581111561140a575061151b565b60008b841611156115085761141d612a3c565b8982815181106114305761142f613abd565b5b602002602001015181600001819052508f8b8151811061145357611452613abd565b5b60200260200101518160200181815250508e8b8151811061147757611476613abd565b5b6020026020010151816040019067ffffffffffffffff16908167ffffffffffffffff16815250508d8b815181106114b1576114b0613abd565b5b6020026020010151816060019067ffffffffffffffff16908167ffffffffffffffff168152505080868c815181106114ec576114eb613abd565b5b602002602001018190525060018b61150491906142b9565b9a50505b60018b901b9a50816001019150506113cd565b50610100820191505061139f565b50809e505050505050505050505050505050919050565b6000606560009054906101000a900460ff16905090565b609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611585611fb8565b61158f600061231f565b565b60008060019054906101000a900460ff161590508080156115c25750600160008054906101000a900460ff1660ff16105b806115ef57506115d1306123e5565b1580156115ee5750600160008054906101000a900460ff1660ff16145b5b61162e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116259061435f565b60405180910390fd5b60016000806101000a81548160ff021916908360ff160217905550801561166b576001600060016101000a81548160ff0219169083151502179055505b611673612408565b61167b612461565b6116d2600067ffffffffffffffff81111561169957611698612e05565b5b6040519080825280602002602001820160405280156116cc57816020015b60608152602001906001900390816116b75790505b50612206565b801561172b5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161172291906143ba565b60405180910390a15b50565b609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61175c611fb8565b6117646124ba565b565b6099602052816000526040600020818051602081018201805184825260208301602085012081835280955050505050506000915091509054906101000a900460ff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b609c5481565b6117e3611fb8565b6000810361181d576040517f831761d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609e819055507f6e8a187d7944998085dbd1f16b84c51c903bb727536cdba86962439aded2cfd7609e546040516118559190613073565b60405180910390a150565b609a60009054906101000a900463ffffffff1681565b61187e612a7b565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3112a64846040518263ffffffff1660e01b81526004016118db91906132ff565b600060405180830381865afa1580156118f8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061192191906145a2565b905080915050919050565b611934611fb8565b6000801b8103611970576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609c819055507feffcfd1add745716a37d406c77e2b9102d465752c93eab2cb1aa1d2e50a08f2f816040516119a691906132ff565b60405180910390a150565b6119b9611fb8565b6000801b81036119f5576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609b819055507feffcfd1add745716a37d406c77e2b9102d465752c93eab2cb1aa1d2e50a08f2f81604051611a2b91906132ff565b60405180910390a150565b609d60009054906101000a900467ffffffffffffffff1681565b609b5481565b611a5e611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ac4576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f663afa59423b5a718ce16629b25a640a45cf2f149146e62347cfc12b5a49b39f81604051611b349190613621565b60405180910390a150565b600080609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d2a3c0f846040518263ffffffff1660e01b8152600401611b9d9190613621565b606060405180830381865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde9190614664565b90506000816020015167ffffffffffffffff1614611c5857611bff8161251d565b15611c455780602001516040517f06c09405000000000000000000000000000000000000000000000000000000008152600401611c3c919061386a565b60405180910390fd5b806000015163ffffffff16915050611e4f565b6000609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379300e5685609c546040518363ffffffff1660e01b8152600401611cb9929190613e45565b602060405180830381865afa158015611cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfa9190613e83565b90506000801b8103611d38576040517f120a2e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d4382611876565b9050600080826101200151806020019051810190611d6191906146bd565b9050809250819350505060048160ff161115611da257600481611d849190614710565b600a611d909190614878565b82611d9b91906148f2565b9150611dd6565b60048160ff161015611dd557806004611dbb9190614710565b600a611dc79190614878565b82611dd29190614277565b91505b5b611ddf83612587565b15611e4657609d60009054906101000a900467ffffffffffffffff168360400151611e0a9190614923565b6040517f06c09405000000000000000000000000000000000000000000000000000000008152600401611e3d919061386a565b60405180910390fd5b81955050505050505b919050565b611e5c611fb8565b60008167ffffffffffffffff1603611ea0576040517f91846b2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609d60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fadc24208c2c2249042b1d37e23d983fe99d452c60ebb70267b3a1274c49f9026609d60009054906101000a900467ffffffffffffffff16604051611f0e9190614990565b60405180910390a150565b611f21611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8790614a1d565b60405180910390fd5b611f998161231f565b50565b600080611fa883611b3f565b9050609e54811015915050919050565b611fc06125f1565b73ffffffffffffffffffffffffffffffffffffffff16611fde6117ab565b73ffffffffffffffffffffffffffffffffffffffff1614612034576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202b90614a89565b60405180910390fd5b565b60006120647f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6125f9565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612095611fb8565b50565b6120c47f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b612603565b60000160009054906101000a900460ff16156120e8576120e38361260d565b612201565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561215057506040513d601f19601f8201168201806040525081019061214d9190613e83565b60015b61218f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218690614b1b565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b81146121f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121eb90614bad565b60405180910390fd5b506122008383836126c6565b5b505050565b60005b815181101561227257600082828151811061222757612226613abd565b5b60200260200101515103612267576040517f88998c5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001019050612209565b508060986000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200190815260200160002090805190602001906122b8929190612b23565b5050565b6122c46126f2565b6000606560006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6123086125f1565b6040516123159190613621565b60405180910390a1565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff16612457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161244e90614c3f565b60405180910390fd5b61245f61273b565b565b600060019054906101000a900460ff166124b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124a790614c3f565b60405180910390fd5b6124b861279c565b565b6124c2612808565b6001606560006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125066125f1565b6040516125139190613621565b60405180910390a1565b600080826040015167ffffffffffffffff16111561254d57816040015167ffffffffffffffff1642119050612582565b609d60009054906101000a900467ffffffffffffffff1682602001516125739190614923565b67ffffffffffffffff16421190505b919050565b600080826060015167ffffffffffffffff1611156125b757816060015167ffffffffffffffff16421190506125ec565b609d60009054906101000a900467ffffffffffffffff1682604001516125dd9190614923565b67ffffffffffffffff16421190505b919050565b600033905090565b6000819050919050565b6000819050919050565b61261681612852565b612655576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161264c90614cd1565b60405180910390fd5b806126827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6125f9565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6126cf83612875565b6000825111806126dc5750805b156126ed576126eb83836128c4565b505b505050565b6126fa611540565b612739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273090614d3d565b60405180910390fd5b565b600060019054906101000a900460ff1661278a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278190614c3f565b60405180910390fd5b61279a6127956125f1565b61231f565b565b600060019054906101000a900460ff166127eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e290614c3f565b60405180910390fd5b6000606560006101000a81548160ff021916908315150217905550565b612810611540565b15612850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161284790614da9565b60405180910390fd5b565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b61287e8161260d565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b60606128e98383604051806060016040528060278152602001614e89602791396128f1565b905092915050565b60606000808573ffffffffffffffffffffffffffffffffffffffff168560405161291b9190614e05565b600060405180830381855af49150503d8060008114612956576040519150601f19603f3d011682016040523d82523d6000602084013e61295b565b606091505b509150915061296c86838387612977565b925050509392505050565b606083156129d95760008351036129d15761299185612852565b6129d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c790614e68565b60405180910390fd5b5b8290506129e4565b6129e383836129ec565b5b949350505050565b6000825111156129ff5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a339190612d53565b60405180910390fd5b60405180608001604052806060815260200160008019168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff1681525090565b6040518061014001604052806000801916815260200160008019168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff16815260200160008019168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001606081525090565b828054828255906000526020600020908101928215612b6b579160200282015b82811115612b6a578251829081612b5a9190613ce1565b5091602001919060010190612b43565b5b509050612b789190612b7c565b5090565b5b80821115612b9c5760008181612b939190612ba0565b50600101612b7d565b5090565b508054612bac9061390d565b6000825580601f10612bbe5750612bdd565b601f016020900490600052602060002090810190612bdc9190612be0565b5b50565b5b80821115612bf9576000816000905550600101612be1565b5090565b6000604051905090565b600080fd5b600080fd5b600063ffffffff82169050919050565b612c2a81612c11565b8114612c3557600080fd5b50565b600081359050612c4781612c21565b92915050565b6000819050919050565b612c6081612c4d565b8114612c6b57600080fd5b50565b600081359050612c7d81612c57565b92915050565b60008060408385031215612c9a57612c99612c07565b5b6000612ca885828601612c38565b9250506020612cb985828601612c6e565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612cfd578082015181840152602081019050612ce2565b60008484015250505050565b6000601f19601f8301169050919050565b6000612d2582612cc3565b612d2f8185612cce565b9350612d3f818560208601612cdf565b612d4881612d09565b840191505092915050565b60006020820190508181036000830152612d6d8184612d1a565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612da082612d75565b9050919050565b612db081612d95565b8114612dbb57600080fd5b50565b600081359050612dcd81612da7565b92915050565b600060208284031215612de957612de8612c07565b5b6000612df784828501612dbe565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612e3d82612d09565b810181811067ffffffffffffffff82111715612e5c57612e5b612e05565b5b80604052505050565b6000612e6f612bfd565b9050612e7b8282612e34565b919050565b600067ffffffffffffffff821115612e9b57612e9a612e05565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115612ed157612ed0612e05565b5b612eda82612d09565b9050602081019050919050565b82818337600083830152505050565b6000612f09612f0484612eb6565b612e65565b905082815260208101848484011115612f2557612f24612eb1565b5b612f30848285612ee7565b509392505050565b600082601f830112612f4d57612f4c612e00565b5b8135612f5d848260208601612ef6565b91505092915050565b6000612f79612f7484612e80565b612e65565b90508083825260208201905060208402830185811115612f9c57612f9b612eac565b5b835b81811015612fe357803567ffffffffffffffff811115612fc157612fc0612e00565b5b808601612fce8982612f38565b85526020850194505050602081019050612f9e565b5050509392505050565b600082601f83011261300257613001612e00565b5b8135613012848260208601612f66565b91505092915050565b60006020828403121561303157613030612c07565b5b600082013567ffffffffffffffff81111561304f5761304e612c0c565b5b61305b84828501612fed565b91505092915050565b61306d81612c4d565b82525050565b60006020820190506130886000830184613064565b92915050565b6000602082840312156130a4576130a3612c07565b5b60006130b284828501612c38565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061310382612cc3565b61310d81856130e7565b935061311d818560208601612cdf565b61312681612d09565b840191505092915050565b600061313d83836130f8565b905092915050565b6000602082019050919050565b600061315d826130bb565b61316781856130c6565b935083602082028501613179856130d7565b8060005b858110156131b557848403895281516131968582613131565b94506131a183613145565b925060208a0199505060018101905061317d565b50829750879550505050505092915050565b600060208201905081810360008301526131e18184613152565b905092915050565b600067ffffffffffffffff82111561320457613203612e05565b5b61320d82612d09565b9050602081019050919050565b600061322d613228846131e9565b612e65565b90508281526020810184848401111561324957613248612eb1565b5b613254848285612ee7565b509392505050565b600082601f83011261327157613270612e00565b5b813561328184826020860161321a565b91505092915050565b600080604083850312156132a1576132a0612c07565b5b60006132af85828601612dbe565b925050602083013567ffffffffffffffff8111156132d0576132cf612c0c565b5b6132dc8582860161325c565b9150509250929050565b6000819050919050565b6132f9816132e6565b82525050565b600060208201905061331460008301846132f0565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61334f816132e6565b82525050565b600067ffffffffffffffff82169050919050565b61337281613355565b82525050565b6000608083016000830151848203600086015261339582826130f8565b91505060208301516133aa6020860182613346565b5060408301516133bd6040860182613369565b5060608301516133d06060860182613369565b508091505092915050565b60006133e78383613378565b905092915050565b6000602082019050919050565b60006134078261331a565b6134118185613325565b93508360208202850161342385613336565b8060005b8581101561345f578484038952815161344085826133db565b945061344b836133ef565b925060208a01995050600181019050613427565b50829750879550505050505092915050565b6000602082019050818103600083015261348b81846133fc565b905092915050565b60008115159050919050565b6134a881613493565b82525050565b60006020820190506134c3600083018461349f565b92915050565b6000819050919050565b60006134ee6134e96134e484612d75565b6134c9565b612d75565b9050919050565b6000613500826134d3565b9050919050565b6000613512826134f5565b9050919050565b61352281613507565b82525050565b600060208201905061353d6000830184613519565b92915050565b600061354e826134f5565b9050919050565b61355e81613543565b82525050565b60006020820190506135796000830184613555565b92915050565b6000806040838503121561359657613595612c07565b5b60006135a485828601612c38565b925050602083013567ffffffffffffffff8111156135c5576135c4612c0c565b5b6135d185828601612f38565b9150509250929050565b600060ff82169050919050565b6135f1816135db565b82525050565b600060208201905061360c60008301846135e8565b92915050565b61361b81612d95565b82525050565b60006020820190506136366000830184613612565b92915050565b60006020828403121561365257613651612c07565b5b600061366084828501612c6e565b91505092915050565b61367281612c11565b82525050565b600060208201905061368d6000830184613669565b92915050565b61369c816132e6565b81146136a757600080fd5b50565b6000813590506136b981613693565b92915050565b6000602082840312156136d5576136d4612c07565b5b60006136e3848285016136aa565b91505092915050565b6136f581612d95565b82525050565b61370481613493565b82525050565b600081519050919050565b600082825260208201905092915050565b60006137318261370a565b61373b8185613715565b935061374b818560208601612cdf565b61375481612d09565b840191505092915050565b6000610140830160008301516137786000860182613346565b50602083015161378b6020860182613346565b50604083015161379e6040860182613369565b5060608301516137b16060860182613369565b5060808301516137c46080860182613369565b5060a08301516137d760a0860182613346565b5060c08301516137ea60c08601826136ec565b5060e08301516137fd60e08601826136ec565b506101008301516138126101008601826136fb565b5061012083015184820361012086015261382c8282613726565b9150508091505092915050565b60006020820190508181036000830152613853818461375f565b905092915050565b61386481613355565b82525050565b600060208201905061387f600083018461385b565b92915050565b61388e81613355565b811461389957600080fd5b50565b6000813590506138ab81613885565b92915050565b6000602082840312156138c7576138c6612c07565b5b60006138d58482850161389c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061392557607f821691505b602082108103613938576139376138de565b5b50919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015250565b600061399a602c83612cce565b91506139a58261393e565b604082019050919050565b600060208201905081810360008301526139c98161398d565b9050919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f6163746976652070726f78790000000000000000000000000000000000000000602082015250565b6000613a2c602c83612cce565b9150613a37826139d0565b604082019050919050565b60006020820190508181036000830152613a5b81613a1f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a9c82612c11565b915063ffffffff8203613ab257613ab1613a62565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081905092915050565b6000613b0282612cc3565b613b0c8185613aec565b9350613b1c818560208601612cdf565b80840191505092915050565b6000613b348284613af7565b915081905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613ba17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613b64565b613bab8683613b64565b95508019841693508086168417925050509392505050565b6000613bde613bd9613bd484612c4d565b6134c9565b612c4d565b9050919050565b6000819050919050565b613bf883613bc3565b613c0c613c0482613be5565b848454613b71565b825550505050565b600090565b613c21613c14565b613c2c818484613bef565b505050565b5b81811015613c5057613c45600082613c19565b600181019050613c32565b5050565b601f821115613c9557613c6681613b3f565b613c6f84613b54565b81016020851015613c7e578190505b613c92613c8a85613b54565b830182613c31565b50505b505050565b600082821c905092915050565b6000613cb860001984600802613c9a565b1980831691505092915050565b6000613cd18383613ca7565b9150826002028217905092915050565b613cea82612cc3565b67ffffffffffffffff811115613d0357613d02612e05565b5b613d0d825461390d565b613d18828285613c54565b600060209050601f831160018114613d4b5760008415613d39578287015190505b613d438582613cc5565b865550613dab565b601f198416613d5986613b3f565b60005b82811015613d8157848901518255600182019150602085019450602081019050613d5c565b86831015613d9e5784890151613d9a601f891682613ca7565b8355505b6001600288020188555050505b505050505050565b7f555550535570677261646561626c653a206d757374206e6f742062652063616c60008201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015250565b6000613e0f603883612cce565b9150613e1a82613db3565b604082019050919050565b60006020820190508181036000830152613e3e81613e02565b9050919050565b6000604082019050613e5a6000830185613612565b613e6760208301846132f0565b9392505050565b600081519050613e7d81613693565b92915050565b600060208284031215613e9957613e98612c07565b5b6000613ea784828501613e6e565b91505092915050565b600067ffffffffffffffff821115613ecb57613eca612e05565b5b602082029050602081019050919050565b600081519050613eeb81612c57565b92915050565b6000613f04613eff84613eb0565b612e65565b90508083825260208201905060208402830185811115613f2757613f26612eac565b5b835b81811015613f505780613f3c8882613edc565b845260208401935050602081019050613f29565b5050509392505050565b600082601f830112613f6f57613f6e612e00565b5b8151613f7f848260208601613ef1565b91505092915050565b600067ffffffffffffffff821115613fa357613fa2612e05565b5b602082029050602081019050919050565b6000613fc7613fc284613f88565b612e65565b90508083825260208201905060208402830185811115613fea57613fe9612eac565b5b835b818110156140135780613fff8882613e6e565b845260208401935050602081019050613fec565b5050509392505050565b600082601f83011261403257614031612e00565b5b8151614042848260208601613fb4565b91505092915050565b600067ffffffffffffffff82111561406657614065612e05565b5b602082029050602081019050919050565b60008151905061408681613885565b92915050565b600061409f61409a8461404b565b612e65565b905080838252602082019050602084028301858111156140c2576140c1612eac565b5b835b818110156140eb57806140d78882614077565b8452602084019350506020810190506140c4565b5050509392505050565b600082601f83011261410a57614109612e00565b5b815161411a84826020860161408c565b91505092915050565b600061ffff82169050919050565b61413a81614123565b811461414557600080fd5b50565b60008151905061415781614131565b92915050565b600080600080600060a0868803121561417957614178612c07565b5b600086015167ffffffffffffffff81111561419757614196612c0c565b5b6141a388828901613f5a565b955050602086015167ffffffffffffffff8111156141c4576141c3612c0c565b5b6141d08882890161401d565b945050604086015167ffffffffffffffff8111156141f1576141f0612c0c565b5b6141fd888289016140f5565b935050606086015167ffffffffffffffff81111561421e5761421d612c0c565b5b61422a888289016140f5565b925050608061423b88828901614148565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600061428282612c4d565b915061428d83612c4d565b925082820261429b81612c4d565b915082820484148315176142b2576142b1613a62565b5b5092915050565b60006142c482612c4d565b91506142cf83612c4d565b92508282019050808211156142e7576142e6613a62565b5b92915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614349602e83612cce565b9150614354826142ed565b604082019050919050565b600060208201905081810360008301526143788161433c565b9050919050565b6000819050919050565b60006143a461439f61439a8461437f565b6134c9565b6135db565b9050919050565b6143b481614389565b82525050565b60006020820190506143cf60008301846143ab565b92915050565b600080fd5b600080fd5b6000815190506143ee81612da7565b92915050565b6143fd81613493565b811461440857600080fd5b50565b60008151905061441a816143f4565b92915050565b600061443361442e846131e9565b612e65565b90508281526020810184848401111561444f5761444e612eb1565b5b61445a848285612cdf565b509392505050565b600082601f83011261447757614476612e00565b5b8151614487848260208601614420565b91505092915050565b600061014082840312156144a7576144a66143d5565b5b6144b2610140612e65565b905060006144c284828501613e6e565b60008301525060206144d684828501613e6e565b60208301525060406144ea84828501614077565b60408301525060606144fe84828501614077565b606083015250608061451284828501614077565b60808301525060a061452684828501613e6e565b60a08301525060c061453a848285016143df565b60c08301525060e061454e848285016143df565b60e0830152506101006145638482850161440b565b6101008301525061012082015167ffffffffffffffff811115614589576145886143da565b5b61459584828501614462565b6101208301525092915050565b6000602082840312156145b8576145b7612c07565b5b600082015167ffffffffffffffff8111156145d6576145d5612c0c565b5b6145e284828501614490565b91505092915050565b6000815190506145fa81612c21565b92915050565b600060608284031215614616576146156143d5565b5b6146206060612e65565b90506000614630848285016145eb565b600083015250602061464484828501614077565b602083015250604061465884828501614077565b60408301525092915050565b60006060828403121561467a57614679612c07565b5b600061468884828501614600565b91505092915050565b61469a816135db565b81146146a557600080fd5b50565b6000815190506146b781614691565b92915050565b6000806000606084860312156146d6576146d5612c07565b5b60006146e486828701613edc565b93505060206146f5868287016145eb565b9250506040614706868287016146a8565b9150509250925092565b600061471b826135db565b9150614726836135db565b9250828203905060ff81111561473f5761473e613a62565b5b92915050565b60008160011c9050919050565b6000808291508390505b600185111561479c5780860481111561477857614777613a62565b5b60018516156147875780820291505b808102905061479585614745565b945061475c565b94509492505050565b6000826147b55760019050614871565b816147c35760009050614871565b81600181146147d957600281146147e357614812565b6001915050614871565b60ff8411156147f5576147f4613a62565b5b8360020a91508482111561480c5761480b613a62565b5b50614871565b5060208310610133831016604e8410600b84101617156148475782820a90508381111561484257614841613a62565b5b614871565b6148548484846001614752565b9250905081840481111561486b5761486a613a62565b5b81810290505b9392505050565b600061488382612c4d565b915061488e836135db565b92506148bb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846147a5565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148fd82612c4d565b915061490883612c4d565b925082614918576149176148c3565b5b828204905092915050565b600061492e82613355565b915061493983613355565b9250828201905067ffffffffffffffff81111561495957614958613a62565b5b92915050565b600061497a61497561497084613355565b6134c9565b612c4d565b9050919050565b61498a8161495f565b82525050565b60006020820190506149a56000830184614981565b92915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614a07602683612cce565b9150614a12826149ab565b604082019050919050565b60006020820190508181036000830152614a36816149fa565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614a73602083612cce565b9150614a7e82614a3d565b602082019050919050565b60006020820190508181036000830152614aa281614a66565b9050919050565b7f45524331393637557067726164653a206e657720696d706c656d656e7461746960008201527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015250565b6000614b05602e83612cce565b9150614b1082614aa9565b604082019050919050565b60006020820190508181036000830152614b3481614af8565b9050919050565b7f45524331393637557067726164653a20756e737570706f727465642070726f7860008201527f6961626c65555549440000000000000000000000000000000000000000000000602082015250565b6000614b97602983612cce565b9150614ba282614b3b565b604082019050919050565b60006020820190508181036000830152614bc681614b8a565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614c29602b83612cce565b9150614c3482614bcd565b604082019050919050565b60006020820190508181036000830152614c5881614c1c565b9050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b6000614cbb602d83612cce565b9150614cc682614c5f565b604082019050919050565b60006020820190508181036000830152614cea81614cae565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000614d27601483612cce565b9150614d3282614cf1565b602082019050919050565b60006020820190508181036000830152614d5681614d1a565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614d93601083612cce565b9150614d9e82614d5d565b602082019050919050565b60006020820190508181036000830152614dc281614d86565b9050919050565b600081905092915050565b6000614ddf8261370a565b614de98185614dc9565b9350614df9818560208601612cdf565b80840191505092915050565b6000614e118284614dd4565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e52601d83612cce565b9150614e5d82614e1c565b602082019050919050565b60006020820190508181036000830152614e8181614e45565b905091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212200fc3e3ff7c4c3badf7a3be17a0464bf509773f62c9b791ef113b2a422b1ad5f264736f6c63430008130033
Deployed Bytecode
0x6080604052600436106101e35760003560e01c80638456cb5911610102578063bb169f7f11610095578063d47875d011610064578063d47875d014610687578063e4a59209146106c4578063f2fde38b146106ed578063f72c436f14610716576101e3565b8063bb169f7f146105df578063c82bfbb714610608578063ceab398814610633578063d2ae372c1461065e576101e3565b8063960bfe04116100d1578063960bfe04146105255780639d888e861461054e578063a3112a6414610579578063a46767b5146105b6576101e3565b80638456cb591461047b57806386b69e8a146104925780638da5cb5b146104cf57806391c70059146104fa576101e3565b80634f1ef2861161017a5780635e33ef5d116101495780635e33ef5d146103f7578063715018a6146104225780638129fc1c146104395780638150864d14610450576101e3565b80634f1ef2861461034857806352d1902d1461036457806357a5893c1461038f5780635c975abb146103cc576101e3565b80633f4ba83a116101b65780633f4ba83a146102a0578063420b7589146102b757806342cde4e8146102e05780634e62cf3f1461030b576101e3565b80631cd191e8146101e85780632e314f65146102255780633659cfe61461024e5780633923d3ef14610277575b600080fd5b3480156101f457600080fd5b5061020f600480360381019061020a9190612c83565b610753565b60405161021c9190612d53565b60405180910390f35b34801561023157600080fd5b5061024c60048036038101906102479190612dd3565b61080c565b005b34801561025a57600080fd5b5061027560048036038101906102709190612dd3565b6108f5565b005b34801561028357600080fd5b5061029e6004803603810190610299919061301b565b610a7d565b005b3480156102ac57600080fd5b506102b5610afe565b005b3480156102c357600080fd5b506102de60048036038101906102d9919061301b565b610b10565b005b3480156102ec57600080fd5b506102f5610d94565b6040516103029190613073565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d919061308e565b610d9a565b60405161033f91906131c7565b60405180910390f35b610362600480360381019061035d919061328a565b610e92565b005b34801561037057600080fd5b50610379610fce565b60405161038691906132ff565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190612dd3565b611087565b6040516103c39190613471565b60405180910390f35b3480156103d857600080fd5b506103e1611540565b6040516103ee91906134ae565b60405180910390f35b34801561040357600080fd5b5061040c611557565b6040516104199190613528565b60405180910390f35b34801561042e57600080fd5b5061043761157d565b005b34801561044557600080fd5b5061044e611591565b005b34801561045c57600080fd5b5061046561172e565b6040516104729190613564565b60405180910390f35b34801561048757600080fd5b50610490611754565b005b34801561049e57600080fd5b506104b960048036038101906104b4919061357f565b611766565b6040516104c691906135f7565b60405180910390f35b3480156104db57600080fd5b506104e46117ab565b6040516104f19190613621565b60405180910390f35b34801561050657600080fd5b5061050f6117d5565b60405161051c91906132ff565b60405180910390f35b34801561053157600080fd5b5061054c6004803603810190610547919061363c565b6117db565b005b34801561055a57600080fd5b50610563611860565b6040516105709190613678565b60405180910390f35b34801561058557600080fd5b506105a0600480360381019061059b91906136bf565b611876565b6040516105ad9190613839565b60405180910390f35b3480156105c257600080fd5b506105dd60048036038101906105d891906136bf565b61192c565b005b3480156105eb57600080fd5b50610606600480360381019061060191906136bf565b6119b1565b005b34801561061457600080fd5b5061061d611a36565b60405161062a919061386a565b60405180910390f35b34801561063f57600080fd5b50610648611a50565b60405161065591906132ff565b60405180910390f35b34801561066a57600080fd5b5061068560048036038101906106809190612dd3565b611a56565b005b34801561069357600080fd5b506106ae60048036038101906106a99190612dd3565b611b3f565b6040516106bb9190613073565b60405180910390f35b3480156106d057600080fd5b506106eb60048036038101906106e691906138b1565b611e54565b005b3480156106f957600080fd5b50610714600480360381019061070f9190612dd3565b611f19565b005b34801561072257600080fd5b5061073d60048036038101906107389190612dd3565b611f9c565b60405161074a91906134ae565b60405180910390f35b6098602052816000526040600020818154811061076f57600080fd5b9060005260206000200160009150915050805461078b9061390d565b80601f01602080910402602001604051908101604052809291908181526020018280546107b79061390d565b80156108045780601f106107d957610100808354040283529160200191610804565b820191906000526020600020905b8154815290600101906020018083116107e757829003601f168201915b505050505081565b610814611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361087a576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609a60046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f14dc79d338b451b8b7b20e3191752ac97cbc8b011ff3b921597b83b1222896ae816040516108ea9190613621565b60405180910390a150565b7f000000000000000000000000fc40a800757c6436b6fc314f9c83bb2ddc384d8b73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1603610983576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097a906139b0565b60405180910390fd5b7f000000000000000000000000fc40a800757c6436b6fc314f9c83bb2ddc384d8b73ffffffffffffffffffffffffffffffffffffffff166109c2612036565b73ffffffffffffffffffffffffffffffffffffffff1614610a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0f90613a42565b60405180910390fd5b610a218161208d565b610a7a81600067ffffffffffffffff811115610a4057610a3f612e05565b5b6040519080825280601f01601f191660200182016040528015610a725781602001600182028036833780820191505090505b506000612098565b50565b610a85611fb8565b609a600081819054906101000a900463ffffffff1680929190610aa790613a91565b91906101000a81548163ffffffff021916908363ffffffff16021790555050610acf81612206565b7f4e210ed25abf187b8a2f6c516deef88d958c75e285b05928d7db0f8a673ce25f60405160405180910390a150565b610b06611fb8565b610b0e6122bc565b565b610b18611fb8565b60005b8151811015610d59576000828281518110610b3957610b38613abd565b5b60200260200101515103610b79576040517f88998c5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160996000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020838381518110610bbf57610bbe613abd565b5b6020026020010151604051610bd49190613b28565b908152602001604051809103902060009054906101000a900460ff1660ff1603610c4f57818181518110610c0b57610c0a613abd565b5b60200260200101516040517fee118ba6000000000000000000000000000000000000000000000000000000008152600401610c469190612d53565b60405180910390fd5b60986000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020828281518110610c9357610c92613abd565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509081610ccc9190613ce1565b50600160996000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020838381518110610d1357610d12613abd565b5b6020026020010151604051610d289190613b28565b908152602001604051809103902060006101000a81548160ff021916908360ff160217905550806001019050610b1b565b507fec76e5d73810a27d70d44fe10dd9040c9c446187c33df2ae02ceb4b07cfa7eb781604051610d8991906131c7565b60405180910390a150565b609e5481565b6060609860008363ffffffff1663ffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610e87578382906000526020600020018054610dfa9061390d565b80601f0160208091040260200160405190810160405280929190818152602001828054610e269061390d565b8015610e735780601f10610e4857610100808354040283529160200191610e73565b820191906000526020600020905b815481529060010190602001808311610e5657829003601f168201915b505050505081526020019060010190610ddb565b505050509050919050565b7f000000000000000000000000fc40a800757c6436b6fc314f9c83bb2ddc384d8b73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1603610f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f17906139b0565b60405180910390fd5b7f000000000000000000000000fc40a800757c6436b6fc314f9c83bb2ddc384d8b73ffffffffffffffffffffffffffffffffffffffff16610f5f612036565b73ffffffffffffffffffffffffffffffffffffffff1614610fb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fac90613a42565b60405180910390fd5b610fbe8261208d565b610fca82826001612098565b5050565b60007f000000000000000000000000fc40a800757c6436b6fc314f9c83bb2ddc384d8b73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161461105e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105590613e25565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905090565b60606000609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379300e5684609b546040518363ffffffff1660e01b81526004016110ea929190613e45565b602060405180830381865afa158015611107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112b9190613e83565b90506000801b8103611169576040517f120a2e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061117482611876565b90506000816060015167ffffffffffffffff161180156111a2575042816060015167ffffffffffffffff1611155b156111e85780606001516040517f06c094050000000000000000000000000000000000000000000000000000000081526004016111df919061386a565b60405180910390fd5b6060806060806000856101200151806020019051810190611209919061415d565b8095508196508297508398508499505050505050600080600090506000609860008561ffff1663ffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561130f5783829060005260206000200180546112829061390d565b80601f01602080910402602001604051908101604052809291908181526020018280546112ae9061390d565b80156112fb5780601f106112d0576101008083540402835291602001916112fb565b820191906000526020600020905b8154815290600101906020018083116112de57829003601f168201915b505050505081526020019060010190611263565b5050505090506000875190506000895190506000835190508851831480156113375750875183145b61134457611343614248565b5b60008367ffffffffffffffff8111156113605761135f612e05565b5b60405190808252806020026020018201604052801561139957816020015b611386612a3c565b81526020019060019003908161137e5790505b50905060005b83811015611529576001975060008d82815181106113c0576113bf613abd565b5b6020026020010151905060005b61010081101561151b578689101561151b57600081610100856113f09190614277565b6113fa91906142b9565b90508581111561140a575061151b565b60008b841611156115085761141d612a3c565b8982815181106114305761142f613abd565b5b602002602001015181600001819052508f8b8151811061145357611452613abd565b5b60200260200101518160200181815250508e8b8151811061147757611476613abd565b5b6020026020010151816040019067ffffffffffffffff16908167ffffffffffffffff16815250508d8b815181106114b1576114b0613abd565b5b6020026020010151816060019067ffffffffffffffff16908167ffffffffffffffff168152505080868c815181106114ec576114eb613abd565b5b602002602001018190525060018b61150491906142b9565b9a50505b60018b901b9a50816001019150506113cd565b50610100820191505061139f565b50809e505050505050505050505050505050919050565b6000606560009054906101000a900460ff16905090565b609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611585611fb8565b61158f600061231f565b565b60008060019054906101000a900460ff161590508080156115c25750600160008054906101000a900460ff1660ff16105b806115ef57506115d1306123e5565b1580156115ee5750600160008054906101000a900460ff1660ff16145b5b61162e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116259061435f565b60405180910390fd5b60016000806101000a81548160ff021916908360ff160217905550801561166b576001600060016101000a81548160ff0219169083151502179055505b611673612408565b61167b612461565b6116d2600067ffffffffffffffff81111561169957611698612e05565b5b6040519080825280602002602001820160405280156116cc57816020015b60608152602001906001900390816116b75790505b50612206565b801561172b5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161172291906143ba565b60405180910390a15b50565b609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61175c611fb8565b6117646124ba565b565b6099602052816000526040600020818051602081018201805184825260208301602085012081835280955050505050506000915091509054906101000a900460ff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b609c5481565b6117e3611fb8565b6000810361181d576040517f831761d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609e819055507f6e8a187d7944998085dbd1f16b84c51c903bb727536cdba86962439aded2cfd7609e546040516118559190613073565b60405180910390a150565b609a60009054906101000a900463ffffffff1681565b61187e612a7b565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3112a64846040518263ffffffff1660e01b81526004016118db91906132ff565b600060405180830381865afa1580156118f8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061192191906145a2565b905080915050919050565b611934611fb8565b6000801b8103611970576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609c819055507feffcfd1add745716a37d406c77e2b9102d465752c93eab2cb1aa1d2e50a08f2f816040516119a691906132ff565b60405180910390a150565b6119b9611fb8565b6000801b81036119f5576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609b819055507feffcfd1add745716a37d406c77e2b9102d465752c93eab2cb1aa1d2e50a08f2f81604051611a2b91906132ff565b60405180910390a150565b609d60009054906101000a900467ffffffffffffffff1681565b609b5481565b611a5e611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ac4576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f663afa59423b5a718ce16629b25a640a45cf2f149146e62347cfc12b5a49b39f81604051611b349190613621565b60405180910390a150565b600080609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d2a3c0f846040518263ffffffff1660e01b8152600401611b9d9190613621565b606060405180830381865afa158015611bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bde9190614664565b90506000816020015167ffffffffffffffff1614611c5857611bff8161251d565b15611c455780602001516040517f06c09405000000000000000000000000000000000000000000000000000000008152600401611c3c919061386a565b60405180910390fd5b806000015163ffffffff16915050611e4f565b6000609a60049054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379300e5685609c546040518363ffffffff1660e01b8152600401611cb9929190613e45565b602060405180830381865afa158015611cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfa9190613e83565b90506000801b8103611d38576040517f120a2e7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d4382611876565b9050600080826101200151806020019051810190611d6191906146bd565b9050809250819350505060048160ff161115611da257600481611d849190614710565b600a611d909190614878565b82611d9b91906148f2565b9150611dd6565b60048160ff161015611dd557806004611dbb9190614710565b600a611dc79190614878565b82611dd29190614277565b91505b5b611ddf83612587565b15611e4657609d60009054906101000a900467ffffffffffffffff168360400151611e0a9190614923565b6040517f06c09405000000000000000000000000000000000000000000000000000000008152600401611e3d919061386a565b60405180910390fd5b81955050505050505b919050565b611e5c611fb8565b60008167ffffffffffffffff1603611ea0576040517f91846b2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80609d60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fadc24208c2c2249042b1d37e23d983fe99d452c60ebb70267b3a1274c49f9026609d60009054906101000a900467ffffffffffffffff16604051611f0e9190614990565b60405180910390a150565b611f21611fb8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8790614a1d565b60405180910390fd5b611f998161231f565b50565b600080611fa883611b3f565b9050609e54811015915050919050565b611fc06125f1565b73ffffffffffffffffffffffffffffffffffffffff16611fde6117ab565b73ffffffffffffffffffffffffffffffffffffffff1614612034576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202b90614a89565b60405180910390fd5b565b60006120647f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6125f9565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612095611fb8565b50565b6120c47f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b612603565b60000160009054906101000a900460ff16156120e8576120e38361260d565b612201565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561215057506040513d601f19601f8201168201806040525081019061214d9190613e83565b60015b61218f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218690614b1b565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b81146121f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121eb90614bad565b60405180910390fd5b506122008383836126c6565b5b505050565b60005b815181101561227257600082828151811061222757612226613abd565b5b60200260200101515103612267576040517f88998c5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001019050612209565b508060986000609a60009054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200190815260200160002090805190602001906122b8929190612b23565b5050565b6122c46126f2565b6000606560006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6123086125f1565b6040516123159190613621565b60405180910390a1565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff16612457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161244e90614c3f565b60405180910390fd5b61245f61273b565b565b600060019054906101000a900460ff166124b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124a790614c3f565b60405180910390fd5b6124b861279c565b565b6124c2612808565b6001606560006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125066125f1565b6040516125139190613621565b60405180910390a1565b600080826040015167ffffffffffffffff16111561254d57816040015167ffffffffffffffff1642119050612582565b609d60009054906101000a900467ffffffffffffffff1682602001516125739190614923565b67ffffffffffffffff16421190505b919050565b600080826060015167ffffffffffffffff1611156125b757816060015167ffffffffffffffff16421190506125ec565b609d60009054906101000a900467ffffffffffffffff1682604001516125dd9190614923565b67ffffffffffffffff16421190505b919050565b600033905090565b6000819050919050565b6000819050919050565b61261681612852565b612655576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161264c90614cd1565b60405180910390fd5b806126827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6125f9565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6126cf83612875565b6000825111806126dc5750805b156126ed576126eb83836128c4565b505b505050565b6126fa611540565b612739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273090614d3d565b60405180910390fd5b565b600060019054906101000a900460ff1661278a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278190614c3f565b60405180910390fd5b61279a6127956125f1565b61231f565b565b600060019054906101000a900460ff166127eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e290614c3f565b60405180910390fd5b6000606560006101000a81548160ff021916908315150217905550565b612810611540565b15612850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161284790614da9565b60405180910390fd5b565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b61287e8161260d565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b60606128e98383604051806060016040528060278152602001614e89602791396128f1565b905092915050565b60606000808573ffffffffffffffffffffffffffffffffffffffff168560405161291b9190614e05565b600060405180830381855af49150503d8060008114612956576040519150601f19603f3d011682016040523d82523d6000602084013e61295b565b606091505b509150915061296c86838387612977565b925050509392505050565b606083156129d95760008351036129d15761299185612852565b6129d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c790614e68565b60405180910390fd5b5b8290506129e4565b6129e383836129ec565b5b949350505050565b6000825111156129ff5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a339190612d53565b60405180910390fd5b60405180608001604052806060815260200160008019168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff1681525090565b6040518061014001604052806000801916815260200160008019168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff16815260200160008019168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001606081525090565b828054828255906000526020600020908101928215612b6b579160200282015b82811115612b6a578251829081612b5a9190613ce1565b5091602001919060010190612b43565b5b509050612b789190612b7c565b5090565b5b80821115612b9c5760008181612b939190612ba0565b50600101612b7d565b5090565b508054612bac9061390d565b6000825580601f10612bbe5750612bdd565b601f016020900490600052602060002090810190612bdc9190612be0565b5b50565b5b80821115612bf9576000816000905550600101612be1565b5090565b6000604051905090565b600080fd5b600080fd5b600063ffffffff82169050919050565b612c2a81612c11565b8114612c3557600080fd5b50565b600081359050612c4781612c21565b92915050565b6000819050919050565b612c6081612c4d565b8114612c6b57600080fd5b50565b600081359050612c7d81612c57565b92915050565b60008060408385031215612c9a57612c99612c07565b5b6000612ca885828601612c38565b9250506020612cb985828601612c6e565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612cfd578082015181840152602081019050612ce2565b60008484015250505050565b6000601f19601f8301169050919050565b6000612d2582612cc3565b612d2f8185612cce565b9350612d3f818560208601612cdf565b612d4881612d09565b840191505092915050565b60006020820190508181036000830152612d6d8184612d1a565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612da082612d75565b9050919050565b612db081612d95565b8114612dbb57600080fd5b50565b600081359050612dcd81612da7565b92915050565b600060208284031215612de957612de8612c07565b5b6000612df784828501612dbe565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612e3d82612d09565b810181811067ffffffffffffffff82111715612e5c57612e5b612e05565b5b80604052505050565b6000612e6f612bfd565b9050612e7b8282612e34565b919050565b600067ffffffffffffffff821115612e9b57612e9a612e05565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115612ed157612ed0612e05565b5b612eda82612d09565b9050602081019050919050565b82818337600083830152505050565b6000612f09612f0484612eb6565b612e65565b905082815260208101848484011115612f2557612f24612eb1565b5b612f30848285612ee7565b509392505050565b600082601f830112612f4d57612f4c612e00565b5b8135612f5d848260208601612ef6565b91505092915050565b6000612f79612f7484612e80565b612e65565b90508083825260208201905060208402830185811115612f9c57612f9b612eac565b5b835b81811015612fe357803567ffffffffffffffff811115612fc157612fc0612e00565b5b808601612fce8982612f38565b85526020850194505050602081019050612f9e565b5050509392505050565b600082601f83011261300257613001612e00565b5b8135613012848260208601612f66565b91505092915050565b60006020828403121561303157613030612c07565b5b600082013567ffffffffffffffff81111561304f5761304e612c0c565b5b61305b84828501612fed565b91505092915050565b61306d81612c4d565b82525050565b60006020820190506130886000830184613064565b92915050565b6000602082840312156130a4576130a3612c07565b5b60006130b284828501612c38565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061310382612cc3565b61310d81856130e7565b935061311d818560208601612cdf565b61312681612d09565b840191505092915050565b600061313d83836130f8565b905092915050565b6000602082019050919050565b600061315d826130bb565b61316781856130c6565b935083602082028501613179856130d7565b8060005b858110156131b557848403895281516131968582613131565b94506131a183613145565b925060208a0199505060018101905061317d565b50829750879550505050505092915050565b600060208201905081810360008301526131e18184613152565b905092915050565b600067ffffffffffffffff82111561320457613203612e05565b5b61320d82612d09565b9050602081019050919050565b600061322d613228846131e9565b612e65565b90508281526020810184848401111561324957613248612eb1565b5b613254848285612ee7565b509392505050565b600082601f83011261327157613270612e00565b5b813561328184826020860161321a565b91505092915050565b600080604083850312156132a1576132a0612c07565b5b60006132af85828601612dbe565b925050602083013567ffffffffffffffff8111156132d0576132cf612c0c565b5b6132dc8582860161325c565b9150509250929050565b6000819050919050565b6132f9816132e6565b82525050565b600060208201905061331460008301846132f0565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61334f816132e6565b82525050565b600067ffffffffffffffff82169050919050565b61337281613355565b82525050565b6000608083016000830151848203600086015261339582826130f8565b91505060208301516133aa6020860182613346565b5060408301516133bd6040860182613369565b5060608301516133d06060860182613369565b508091505092915050565b60006133e78383613378565b905092915050565b6000602082019050919050565b60006134078261331a565b6134118185613325565b93508360208202850161342385613336565b8060005b8581101561345f578484038952815161344085826133db565b945061344b836133ef565b925060208a01995050600181019050613427565b50829750879550505050505092915050565b6000602082019050818103600083015261348b81846133fc565b905092915050565b60008115159050919050565b6134a881613493565b82525050565b60006020820190506134c3600083018461349f565b92915050565b6000819050919050565b60006134ee6134e96134e484612d75565b6134c9565b612d75565b9050919050565b6000613500826134d3565b9050919050565b6000613512826134f5565b9050919050565b61352281613507565b82525050565b600060208201905061353d6000830184613519565b92915050565b600061354e826134f5565b9050919050565b61355e81613543565b82525050565b60006020820190506135796000830184613555565b92915050565b6000806040838503121561359657613595612c07565b5b60006135a485828601612c38565b925050602083013567ffffffffffffffff8111156135c5576135c4612c0c565b5b6135d185828601612f38565b9150509250929050565b600060ff82169050919050565b6135f1816135db565b82525050565b600060208201905061360c60008301846135e8565b92915050565b61361b81612d95565b82525050565b60006020820190506136366000830184613612565b92915050565b60006020828403121561365257613651612c07565b5b600061366084828501612c6e565b91505092915050565b61367281612c11565b82525050565b600060208201905061368d6000830184613669565b92915050565b61369c816132e6565b81146136a757600080fd5b50565b6000813590506136b981613693565b92915050565b6000602082840312156136d5576136d4612c07565b5b60006136e3848285016136aa565b91505092915050565b6136f581612d95565b82525050565b61370481613493565b82525050565b600081519050919050565b600082825260208201905092915050565b60006137318261370a565b61373b8185613715565b935061374b818560208601612cdf565b61375481612d09565b840191505092915050565b6000610140830160008301516137786000860182613346565b50602083015161378b6020860182613346565b50604083015161379e6040860182613369565b5060608301516137b16060860182613369565b5060808301516137c46080860182613369565b5060a08301516137d760a0860182613346565b5060c08301516137ea60c08601826136ec565b5060e08301516137fd60e08601826136ec565b506101008301516138126101008601826136fb565b5061012083015184820361012086015261382c8282613726565b9150508091505092915050565b60006020820190508181036000830152613853818461375f565b905092915050565b61386481613355565b82525050565b600060208201905061387f600083018461385b565b92915050565b61388e81613355565b811461389957600080fd5b50565b6000813590506138ab81613885565b92915050565b6000602082840312156138c7576138c6612c07565b5b60006138d58482850161389c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061392557607f821691505b602082108103613938576139376138de565b5b50919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015250565b600061399a602c83612cce565b91506139a58261393e565b604082019050919050565b600060208201905081810360008301526139c98161398d565b9050919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f6163746976652070726f78790000000000000000000000000000000000000000602082015250565b6000613a2c602c83612cce565b9150613a37826139d0565b604082019050919050565b60006020820190508181036000830152613a5b81613a1f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a9c82612c11565b915063ffffffff8203613ab257613ab1613a62565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081905092915050565b6000613b0282612cc3565b613b0c8185613aec565b9350613b1c818560208601612cdf565b80840191505092915050565b6000613b348284613af7565b915081905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613ba17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613b64565b613bab8683613b64565b95508019841693508086168417925050509392505050565b6000613bde613bd9613bd484612c4d565b6134c9565b612c4d565b9050919050565b6000819050919050565b613bf883613bc3565b613c0c613c0482613be5565b848454613b71565b825550505050565b600090565b613c21613c14565b613c2c818484613bef565b505050565b5b81811015613c5057613c45600082613c19565b600181019050613c32565b5050565b601f821115613c9557613c6681613b3f565b613c6f84613b54565b81016020851015613c7e578190505b613c92613c8a85613b54565b830182613c31565b50505b505050565b600082821c905092915050565b6000613cb860001984600802613c9a565b1980831691505092915050565b6000613cd18383613ca7565b9150826002028217905092915050565b613cea82612cc3565b67ffffffffffffffff811115613d0357613d02612e05565b5b613d0d825461390d565b613d18828285613c54565b600060209050601f831160018114613d4b5760008415613d39578287015190505b613d438582613cc5565b865550613dab565b601f198416613d5986613b3f565b60005b82811015613d8157848901518255600182019150602085019450602081019050613d5c565b86831015613d9e5784890151613d9a601f891682613ca7565b8355505b6001600288020188555050505b505050505050565b7f555550535570677261646561626c653a206d757374206e6f742062652063616c60008201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015250565b6000613e0f603883612cce565b9150613e1a82613db3565b604082019050919050565b60006020820190508181036000830152613e3e81613e02565b9050919050565b6000604082019050613e5a6000830185613612565b613e6760208301846132f0565b9392505050565b600081519050613e7d81613693565b92915050565b600060208284031215613e9957613e98612c07565b5b6000613ea784828501613e6e565b91505092915050565b600067ffffffffffffffff821115613ecb57613eca612e05565b5b602082029050602081019050919050565b600081519050613eeb81612c57565b92915050565b6000613f04613eff84613eb0565b612e65565b90508083825260208201905060208402830185811115613f2757613f26612eac565b5b835b81811015613f505780613f3c8882613edc565b845260208401935050602081019050613f29565b5050509392505050565b600082601f830112613f6f57613f6e612e00565b5b8151613f7f848260208601613ef1565b91505092915050565b600067ffffffffffffffff821115613fa357613fa2612e05565b5b602082029050602081019050919050565b6000613fc7613fc284613f88565b612e65565b90508083825260208201905060208402830185811115613fea57613fe9612eac565b5b835b818110156140135780613fff8882613e6e565b845260208401935050602081019050613fec565b5050509392505050565b600082601f83011261403257614031612e00565b5b8151614042848260208601613fb4565b91505092915050565b600067ffffffffffffffff82111561406657614065612e05565b5b602082029050602081019050919050565b60008151905061408681613885565b92915050565b600061409f61409a8461404b565b612e65565b905080838252602082019050602084028301858111156140c2576140c1612eac565b5b835b818110156140eb57806140d78882614077565b8452602084019350506020810190506140c4565b5050509392505050565b600082601f83011261410a57614109612e00565b5b815161411a84826020860161408c565b91505092915050565b600061ffff82169050919050565b61413a81614123565b811461414557600080fd5b50565b60008151905061415781614131565b92915050565b600080600080600060a0868803121561417957614178612c07565b5b600086015167ffffffffffffffff81111561419757614196612c0c565b5b6141a388828901613f5a565b955050602086015167ffffffffffffffff8111156141c4576141c3612c0c565b5b6141d08882890161401d565b945050604086015167ffffffffffffffff8111156141f1576141f0612c0c565b5b6141fd888289016140f5565b935050606086015167ffffffffffffffff81111561421e5761421d612c0c565b5b61422a888289016140f5565b925050608061423b88828901614148565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600061428282612c4d565b915061428d83612c4d565b925082820261429b81612c4d565b915082820484148315176142b2576142b1613a62565b5b5092915050565b60006142c482612c4d565b91506142cf83612c4d565b92508282019050808211156142e7576142e6613a62565b5b92915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614349602e83612cce565b9150614354826142ed565b604082019050919050565b600060208201905081810360008301526143788161433c565b9050919050565b6000819050919050565b60006143a461439f61439a8461437f565b6134c9565b6135db565b9050919050565b6143b481614389565b82525050565b60006020820190506143cf60008301846143ab565b92915050565b600080fd5b600080fd5b6000815190506143ee81612da7565b92915050565b6143fd81613493565b811461440857600080fd5b50565b60008151905061441a816143f4565b92915050565b600061443361442e846131e9565b612e65565b90508281526020810184848401111561444f5761444e612eb1565b5b61445a848285612cdf565b509392505050565b600082601f83011261447757614476612e00565b5b8151614487848260208601614420565b91505092915050565b600061014082840312156144a7576144a66143d5565b5b6144b2610140612e65565b905060006144c284828501613e6e565b60008301525060206144d684828501613e6e565b60208301525060406144ea84828501614077565b60408301525060606144fe84828501614077565b606083015250608061451284828501614077565b60808301525060a061452684828501613e6e565b60a08301525060c061453a848285016143df565b60c08301525060e061454e848285016143df565b60e0830152506101006145638482850161440b565b6101008301525061012082015167ffffffffffffffff811115614589576145886143da565b5b61459584828501614462565b6101208301525092915050565b6000602082840312156145b8576145b7612c07565b5b600082015167ffffffffffffffff8111156145d6576145d5612c0c565b5b6145e284828501614490565b91505092915050565b6000815190506145fa81612c21565b92915050565b600060608284031215614616576146156143d5565b5b6146206060612e65565b90506000614630848285016145eb565b600083015250602061464484828501614077565b602083015250604061465884828501614077565b60408301525092915050565b60006060828403121561467a57614679612c07565b5b600061468884828501614600565b91505092915050565b61469a816135db565b81146146a557600080fd5b50565b6000815190506146b781614691565b92915050565b6000806000606084860312156146d6576146d5612c07565b5b60006146e486828701613edc565b93505060206146f5868287016145eb565b9250506040614706868287016146a8565b9150509250925092565b600061471b826135db565b9150614726836135db565b9250828203905060ff81111561473f5761473e613a62565b5b92915050565b60008160011c9050919050565b6000808291508390505b600185111561479c5780860481111561477857614777613a62565b5b60018516156147875780820291505b808102905061479585614745565b945061475c565b94509492505050565b6000826147b55760019050614871565b816147c35760009050614871565b81600181146147d957600281146147e357614812565b6001915050614871565b60ff8411156147f5576147f4613a62565b5b8360020a91508482111561480c5761480b613a62565b5b50614871565b5060208310610133831016604e8410600b84101617156148475782820a90508381111561484257614841613a62565b5b614871565b6148548484846001614752565b9250905081840481111561486b5761486a613a62565b5b81810290505b9392505050565b600061488382612c4d565b915061488e836135db565b92506148bb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846147a5565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148fd82612c4d565b915061490883612c4d565b925082614918576149176148c3565b5b828204905092915050565b600061492e82613355565b915061493983613355565b9250828201905067ffffffffffffffff81111561495957614958613a62565b5b92915050565b600061497a61497561497084613355565b6134c9565b612c4d565b9050919050565b61498a8161495f565b82525050565b60006020820190506149a56000830184614981565b92915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614a07602683612cce565b9150614a12826149ab565b604082019050919050565b60006020820190508181036000830152614a36816149fa565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614a73602083612cce565b9150614a7e82614a3d565b602082019050919050565b60006020820190508181036000830152614aa281614a66565b9050919050565b7f45524331393637557067726164653a206e657720696d706c656d656e7461746960008201527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015250565b6000614b05602e83612cce565b9150614b1082614aa9565b604082019050919050565b60006020820190508181036000830152614b3481614af8565b9050919050565b7f45524331393637557067726164653a20756e737570706f727465642070726f7860008201527f6961626c65555549440000000000000000000000000000000000000000000000602082015250565b6000614b97602983612cce565b9150614ba282614b3b565b604082019050919050565b60006020820190508181036000830152614bc681614b8a565b9050919050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614c29602b83612cce565b9150614c3482614bcd565b604082019050919050565b60006020820190508181036000830152614c5881614c1c565b9050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b6000614cbb602d83612cce565b9150614cc682614c5f565b604082019050919050565b60006020820190508181036000830152614cea81614cae565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000614d27601483612cce565b9150614d3282614cf1565b602082019050919050565b60006020820190508181036000830152614d5681614d1a565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614d93601083612cce565b9150614d9e82614d5d565b602082019050919050565b60006020820190508181036000830152614dc281614d86565b9050919050565b600081905092915050565b6000614ddf8261370a565b614de98185614dc9565b9350614df9818560208601612cdf565b80840191505092915050565b6000614e118284614dd4565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e52601d83612cce565b9150614e5d82614e1c565b602082019050919050565b60006020820190508181036000830152614e8181614e45565b905091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212200fc3e3ff7c4c3badf7a3be17a0464bf509773f62c9b791ef113b2a422b1ad5f264736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.