Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 20 from a total of 20 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Vouching Lim... | 17693729 | 395 days ago | IN | 0 ETH | 0.00000002 | ||||
| Set Vouching Lim... | 17184920 | 407 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 17084617 | 409 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 17084612 | 409 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 16801229 | 416 days ago | IN | 0 ETH | 0.00000002 | ||||
| Set Vouching Lim... | 16801208 | 416 days ago | IN | 0 ETH | 0.00000002 | ||||
| Set Vouching Lim... | 16801167 | 416 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 16801159 | 416 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 16801151 | 416 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 16801142 | 416 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Vouching Lim... | 16801134 | 416 days ago | IN | 0 ETH | 0.00000005 | ||||
| Update Current S... | 16667815 | 419 days ago | IN | 0 ETH | 0.00017792 | ||||
| Set Vouching Lim... | 16667812 | 419 days ago | IN | 0 ETH | 0.00015109 | ||||
| Set Vouching Lim... | 16667808 | 419 days ago | IN | 0 ETH | 0.00015028 | ||||
| Set Vouching Lim... | 16667804 | 419 days ago | IN | 0 ETH | 0.00014996 | ||||
| Set Vouching Lim... | 16667801 | 419 days ago | IN | 0 ETH | 0.0001503 | ||||
| Set Vouching Lim... | 16667797 | 419 days ago | IN | 0 ETH | 0.00015071 | ||||
| Set Vouching Sea... | 16667795 | 419 days ago | IN | 0 ETH | 0.00030396 | ||||
| Add Manager | 16667794 | 419 days ago | IN | 0 ETH | 0.00016519 | ||||
| Add Manager | 16667791 | 419 days ago | IN | 0 ETH | 0.00016534 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
VouchResolver
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {IEAS, Attestation} from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
import {SchemaResolver} from "@ethereum-attestation-service/eas-contracts/contracts/resolver/SchemaResolver.sol";
/**
* @title VouchResolver: Manager of attestations and vouching seasons
* @author Marto (https://github.com/0xMarto)
* @dev Feel free to make any adjustments to the code (DMs are open @0xMarto)
*/
contract VouchResolver is SchemaResolver, AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
// State objects
struct VouchingSeason {
uint256 startTimestamp; // Season starts date (attest/revokes enabled)
uint256 endTimestamp; // Season ends date (attest/revokes disabled)
uint256 maxTotalVouches; // Max total allowed vouches of the season
uint256 totalVouches; // Total validated vouches of the season
}
struct SeasonVouch {
uint256 totalVouches; // Amount of vouches attested in the season
uint256 lastVouchTimestamp; // Time of last attested vouch in the season
uint256 availableVouches; // Amount of max vouches available in that season
}
struct SchemaInfo {
string platform; // E.g.: "Devcon"
string category; // E.g.: "SocialStereo"
string subCategory; // E.g.: "CutTheLine"
}
// Public variables
uint256 public currentSeason;
mapping(uint256 => VouchingSeason) public vouchingSeasons;
// @dev vouchCode: calculated as keccak256 of the concatenation of the schema parameters (as bytes32)
// @dev accountVouches[accountAddress][seasonNumber][vouchCode]
mapping(address => mapping(uint256 => mapping(bytes32 => SeasonVouch))) public accountVouches;
mapping(bytes32 => uint256) public maxAccountVouches; // Max allowed vouches in one season per Vouch Code
// Modifiers
modifier onlyAdmin() {
require(hasRole(ADMIN_ROLE, msg.sender), "Only Admin");
_;
}
modifier onlyManager() {
require(hasRole(MANAGER_ROLE, msg.sender), "Only Manager");
_;
}
constructor(IEAS eas, address initialAdmin) SchemaResolver(eas) {
// Grant DEFAULT_ADMIN_ROLE to the initial admin (this is the admin to the ADMIN_ROLE list)
_setupRole(DEFAULT_ADMIN_ROLE, initialAdmin);
// Set ADMIN_ROLE as admin of CALLER_ROLE list
_setRoleAdmin(MANAGER_ROLE, ADMIN_ROLE);
// Grant ADMIN_ROLE to initial Admin (this enables to call "addAdmin" helper function)
_setupRole(ADMIN_ROLE, initialAdmin);
}
function onAttest(Attestation calldata attestation, uint256 /*value*/) internal override returns (bool) {
// Get vouch code based on received attestation data
bytes32 vouchCode = _getAttestationVouchCode(attestation);
uint256 codeMaxVouches = maxAccountVouches[vouchCode];
// Get current season and account current vouch state
VouchingSeason storage season = vouchingSeasons[currentSeason];
SeasonVouch storage account = accountVouches[attestation.attester][currentSeason][vouchCode];
// Verify all season and account limits
require(block.timestamp >= season.startTimestamp, "Season not started");
require(block.timestamp < season.endTimestamp, "Season already ended");
require(codeMaxVouches > 0, "Invalid vouch data");
require(season.totalVouches < season.maxTotalVouches, "Season max vouches reach!");
require(account.totalVouches < codeMaxVouches, "Max vouches reach!");
// Register attestation in season and account counters
season.totalVouches += 1;
account.totalVouches += 1;
account.lastVouchTimestamp = block.timestamp;
account.availableVouches = codeMaxVouches; // historical value
return true;
}
function onRevoke(Attestation calldata attestation, uint256 /*value*/) internal override returns (bool) {
// Get vouch code based on received attestation data
bytes32 vouchCode = _getAttestationVouchCode(attestation);
// Get current season and account current vouch state
VouchingSeason storage season = vouchingSeasons[currentSeason];
SeasonVouch storage account = accountVouches[attestation.attester][currentSeason][vouchCode];
// Verify all season and account limits
require(block.timestamp >= season.startTimestamp, "Season not started");
require(block.timestamp < season.endTimestamp, "Season already ended");
require(account.totalVouches > 0 && season.totalVouches > 0, "Invalid revoke!");
// Register attestation revoke in account and season totals
season.totalVouches -= 1;
account.totalVouches -= 1;
return true;
}
// Public helper function
function getVouchCode(
string memory platform, string memory category, string memory subCategory
) external pure returns (bytes32) {
bytes32 platformBytes = _stringToBytes32(platform);
bytes32 categoryBytes = _stringToBytes32(category);
bytes32 subCategoryBytes = _stringToBytes32(subCategory);
return keccak256(abi.encodePacked(platformBytes, categoryBytes, subCategoryBytes));
}
// Whitelisted functions: OnlyManager & Only admin
function updateCurrentSeason(uint256 seasonIndex) external onlyManager {
currentSeason = seasonIndex;
}
function setVouchingSeason(
uint256 seasonIndex,
uint256 startTimestamp,
uint256 endTimestamp,
uint256 maxTotalVouches
) external onlyManager {
vouchingSeasons[seasonIndex] = VouchingSeason({
startTimestamp: startTimestamp,
endTimestamp: endTimestamp,
maxTotalVouches: maxTotalVouches,
totalVouches: vouchingSeasons[seasonIndex].totalVouches
});
}
function setVouchingLimit(bytes32 vouchCode, uint256 limit) external onlyManager {
maxAccountVouches[vouchCode] = limit;
}
function addManager(address account) external onlyAdmin {
grantRole(MANAGER_ROLE, account);
}
function removeManager(address account) external onlyAdmin {
revokeRole(MANAGER_ROLE, account);
}
function addAdmin(address account) external onlyAdmin {
grantRole(ADMIN_ROLE, account);
}
function removeAdmin(address account) external onlyAdmin {
revokeRole(ADMIN_ROLE, account);
}
// Internal/private functions used to decode attestation data
function _getAttestationVouchCode(Attestation calldata attestation) internal pure returns (bytes32) {
return keccak256(attestation.data);
}
function _decodeSchemaInfo(bytes memory _data) internal pure returns (SchemaInfo memory) {
(bytes32 endorsement, bytes32 category, bytes32 platform) = abi.decode(
_data, (bytes32, bytes32, bytes32)
);
return SchemaInfo(
_bytes32ToString(endorsement),
_bytes32ToString(category),
_bytes32ToString(platform)
);
}
function _bytes32ToString(bytes32 _bytes32) internal pure returns (string memory) {
bytes memory bytesArray = new bytes(32);
for (uint i = 0; i < 32; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
function _stringToBytes32(string memory source) internal pure returns (bytes32 result) {
bytes memory tempBytes = abi.encodePacked(source);
if (tempBytes.length > 32) {
revert("String is too long");
}
assembly {
result := mload(add(tempBytes, 32))
}
}
}// 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 { ISemver } from "./ISemver.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 is ISemver {
/// @notice Emitted when an attestation has been made.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param uid The UID of the new 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 { ISemver } from "./ISemver.sol";
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 is ISemver {
/// @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;
/// @title ISemver
/// @notice A semver interface.
interface ISemver {
/// @notice Returns the full semver contract version.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISemver } from "../ISemver.sol";
import { Attestation } from "../Common.sol";
/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver is ISemver {
/// @notice Checks if the resolver can be sent ETH.
/// @return Whether the resolver supports ETH transfers.
function isPayable() external pure returns (bool);
/// @notice Processes an attestation and verifies whether it's valid.
/// @param attestation The new attestation.
/// @return Whether the attestation is valid.
function attest(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes multiple attestations and verifies whether they are valid.
/// @param attestations The new attestations.
/// @param values Explicit ETH amounts which were sent with each attestation.
/// @return Whether all the attestations are valid.
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @return Whether the attestation can be revoked.
function revoke(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes revocation of multiple attestation and verifies they can be revoked.
/// @param attestations The existing attestations to be revoked.
/// @param values Explicit ETH amounts which were sent with each revocation.
/// @return Whether the attestations can be revoked.
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import { IEAS, Attestation } from "../IEAS.sol";
import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "../Common.sol";
import { Semver } from "../Semver.sol";
import { ISchemaResolver } from "./ISchemaResolver.sol";
/// @title SchemaResolver
/// @notice The base schema resolver contract.
abstract contract SchemaResolver is ISchemaResolver, Semver {
error InsufficientValue();
error NotPayable();
// The global EAS contract.
IEAS internal immutable _eas;
/// @dev Creates a new resolver.
/// @param eas The address of the global EAS contract.
constructor(IEAS eas) Semver(1, 3, 0) {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
_eas = eas;
}
/// @dev Ensures that only the EAS contract can make this call.
modifier onlyEAS() {
_onlyEAS();
_;
}
/// @inheritdoc ISchemaResolver
function isPayable() public pure virtual returns (bool) {
return false;
}
/// @dev ETH callback.
receive() external payable virtual {
if (!isPayable()) {
revert NotPayable();
}
}
/// @inheritdoc ISchemaResolver
function attest(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onAttest(attestation, msg.value);
}
/// @inheritdoc ISchemaResolver
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
if (length != values.length) {
revert InvalidLength();
}
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the attestation to the underlying resolver and return false in case it isn't approved.
if (!onAttest(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/// @inheritdoc ISchemaResolver
function revoke(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onRevoke(attestation, msg.value);
}
/// @inheritdoc ISchemaResolver
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
if (length != values.length) {
revert InvalidLength();
}
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the revocation to the underlying resolver and return false in case it isn't approved.
if (!onRevoke(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/// @notice A resolver callback that should be implemented by child contracts.
/// @param attestation The new attestation.
/// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
/// both attest() and multiAttest() callbacks EAS-only callbacks and that in case of multi attestations, it'll
/// usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
/// attestations in the batch.
/// @return Whether the attestation is valid.
function onAttest(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
/// both revoke() and multiRevoke() callbacks EAS-only callbacks and that in case of multi attestations, it'll
/// usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
/// attestations in the batch.
/// @return Whether the attestation can be revoked.
function onRevoke(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/// @dev Ensures that only the EAS contract can make this call.
function _onlyEAS() private view {
if (msg.sender != address(_eas)) {
revert AccessDenied();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { ISemver } from "./ISemver.sol";
/// @title Semver
/// @notice A simple contract for managing contract versions.
contract Semver is ISemver {
// Contract's major version number.
uint256 private immutable _major;
// Contract's minor version number.
uint256 private immutable _minor;
// Contract's patch version number.
uint256 private immutable _patch;
/// @dev Create a new Semver instance.
/// @param major Major version number.
/// @param minor Minor version number.
/// @param patch Patch version number.
constructor(uint256 major, uint256 minor, uint256 patch) {
_major = major;
_minor = minor;
_patch = patch;
}
/// @notice Returns the full semver contract version.
/// @return Semver contract version as a string.
function version() external view returns (string memory) {
return
string(
abi.encodePacked(Strings.toString(_major), ".", Strings.toString(_minor), ".", Strings.toString(_patch))
);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}{
"optimizer": {
"enabled": true,
"runs": 999
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"contract IEAS","name":"eas","type":"address"},{"internalType":"address","name":"initialAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"InvalidEAS","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"NotPayable","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"accountVouches","outputs":[{"internalType":"uint256","name":"totalVouches","type":"uint256"},{"internalType":"uint256","name":"lastVouchTimestamp","type":"uint256"},{"internalType":"uint256","name":"availableVouches","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"attestation","type":"tuple"}],"name":"attest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentSeason","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"platform","type":"string"},{"internalType":"string","name":"category","type":"string"},{"internalType":"string","name":"subCategory","type":"string"}],"name":"getVouchCode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPayable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"maxAccountVouches","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiAttest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"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":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiRevoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"attestation","type":"tuple"}],"name":"revoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vouchCode","type":"bytes32"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setVouchingLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"seasonIndex","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"maxTotalVouches","type":"uint256"}],"name":"setVouchingSeason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"seasonIndex","type":"uint256"}],"name":"updateCurrentSeason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vouchingSeasons","outputs":[{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"maxTotalVouches","type":"uint256"},{"internalType":"uint256","name":"totalVouches","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
61010060405234801561001157600080fd5b506040516120e83803806120e8833981016040819052610030916101e4565b6001608052600360a052600060c052816001600160a01b038116610067576040516341bc07ff60e11b815260040160405180910390fd5b6001600160a01b031660e05261007e6000826100d5565b6100b67f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086000805160206120c88339815191526100e3565b6100ce6000805160206120c8833981519152826100d5565b505061021e565b6100df828261012e565b5050565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166100df576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556101883390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b03811681146101e157600080fd5b50565b600080604083850312156101f757600080fd5b8251610202816101cc565b6020840151909250610213816101cc565b809150509250929050565b60805160a05160c05160e051611e716102576000396000611026015260006108e9015260006108c0015260006108970152611e716000f3fe6080604052600436106101b05760003560e01c806391d14854116100ec578063d547741f1161008a578063e4e81b8011610064578063e4e81b801461053b578063e60c35051461059f578063ec87621c146105b2578063f8f71a76146105e657600080fd5b8063d547741f146104e8578063d6fb7d7914610508578063e49617e11461052857600080fd5b8063ac18de43116100c6578063ac18de431461047e578063bcb396211461049e578063ce46e046146104b4578063d27428f6146104c857600080fd5b806391d148541461041257806391db0b7e14610456578063a217fddf1461046957600080fd5b806349ebb4181161015957806375b238fc1161013357806375b238fc1461038b5780637e6a7e00146103bf578063829efc28146103df57806388e5b2d9146103ff57600080fd5b806349ebb418146102e157806354fd4d5014610349578063704802751461036b57600080fd5b80632d06177a1161018a5780632d06177a146102815780632f2ff15d146102a157806336568abe146102c157600080fd5b806301ffc9a7146101ee5780631785f53c14610223578063248a9ca31461024357600080fd5b366101e9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b600080fd5b3480156101fa57600080fd5b5061020e610209366004611888565b610613565b60405190151581526020015b60405180910390f35b34801561022f57600080fd5b506101e761023e3660046118e1565b6106ac565b34801561024f57600080fd5b5061027361025e3660046118fc565b60009081526020819052604090206001015490565b60405190815260200161021a565b34801561028d57600080fd5b506101e761029c3660046118e1565b610749565b3480156102ad57600080fd5b506101e76102bc366004611915565b6107da565b3480156102cd57600080fd5b506101e76102dc366004611915565b610804565b3480156102ed57600080fd5b5061032e6102fc366004611941565b600360209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161021a565b34801561035557600080fd5b5061035e610890565b60405161021a9190611998565b34801561037757600080fd5b506101e76103863660046118e1565b610933565b34801561039757600080fd5b506102737fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156103cb57600080fd5b506101e76103da3660046119cb565b6109c8565b3480156103eb57600080fd5b506101e76103fa3660046119ed565b610a47565b61020e61040d366004611a6b565b610b07565b34801561041e57600080fd5b5061020e61042d366004611915565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61020e610464366004611a6b565b610bd6565b34801561047557600080fd5b50610273600081565b34801561048a57600080fd5b506101e76104993660046118e1565b610c95565b3480156104aa57600080fd5b5061027360015481565b3480156104c057600080fd5b50600061020e565b3480156104d457600080fd5b506102736104e3366004611b81565b610d2a565b3480156104f457600080fd5b506101e7610503366004611915565b610d90565b34801561051457600080fd5b506101e76105233660046118fc565b610db5565b61020e610536366004611c15565b610e27565b34801561054757600080fd5b5061057f6105563660046118fc565b600260208190526000918252604090912080546001820154928201546003909201549092919084565b60408051948552602085019390935291830152606082015260800161021a565b61020e6105ad366004611c15565b610e40565b3480156105be57600080fd5b506102737f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b3480156105f257600080fd5b506102736106013660046118fc565b60046020526000908152604090205481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806106a657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff1661071c5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b60448201526064015b60405180910390fd5b6107467fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177582610d90565b50565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff166107b45760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08825b6000828152602081905260409020600101546107f581610e54565b6107ff8383610e5e565b505050565b6001600160a01b03811633146108825760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610713565b61088c8282610efc565b5050565b60606108bb7f0000000000000000000000000000000000000000000000000000000000000000610f7b565b6108e47f0000000000000000000000000000000000000000000000000000000000000000610f7b565b61090d7f0000000000000000000000000000000000000000000000000000000000000000610f7b565b60405160200161091f93929190611c51565b604051602081830303815290604052905090565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff1661099e5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775826107da565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610a355760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b60009182526004602052604090912055565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610ab45760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b604080516080810182529384526020808501938452848201928352600086815260028083529281206003810180546060890190815298909252918390529451815592516001840155905191015590519055565b6000610b1161101b565b83828114610b325760405163251f56a160e21b815260040160405180910390fd5b3460005b82811015610bc6576000868683818110610b5257610b52611cb0565b90506020020135905082811115610b7c5760405163044044a560e21b815260040160405180910390fd5b610ba9898984818110610b9157610b91611cb0565b9050602002810190610ba39190611cc6565b8261107f565b610bba576000945050505050610bce565b90910390600101610b36565b506001925050505b949350505050565b6000610be061101b565b83828114610c015760405163251f56a160e21b815260040160405180910390fd5b3460005b82811015610bc6576000868683818110610c2157610c21611cb0565b90506020020135905082811115610c4b5760405163044044a560e21b815260040160405180910390fd5b610c78898984818110610c6057610c60611cb0565b9050602002810190610c729190611cc6565b8261122a565b610c89576000945050505050610bce565b90910390600101610c05565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16610d005760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0882610d90565b600080610d368561148b565b90506000610d438561148b565b90506000610d508561148b565b6040805160208101869052908101849052606081018290529091506080016040516020818303038152906040528051906020012093505050509392505050565b600082815260208190526040902060010154610dab81610e54565b6107ff8383610efc565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610e225760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b600155565b6000610e3161101b565b6106a6823461107f565b919050565b6000610e4a61101b565b6106a6823461122a565b610746813361150c565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661088c576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610eb83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff161561088c576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606000610f888361157f565b600101905060008167ffffffffffffffff811115610fa857610fa8611adc565b6040519080825280601f01601f191660200182016040528015610fd2576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610fdc57509392505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461107d576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008061108b84611661565b60015460009081526002602052604081209192506003816110b3610100890160e08a016118e1565b6001600160a01b031681526020808201929092526040908101600090812060015482528352818120868252909252902082549091504210156111375760405162461bcd60e51b815260206004820152601260248201527f536561736f6e206e6f74207374617274656400000000000000000000000000006044820152606401610713565b8160010154421061118a5760405162461bcd60e51b815260206004820152601460248201527f536561736f6e20616c726561647920656e6465640000000000000000000000006044820152606401610713565b80541580159061119e575060008260030154115b6111ea5760405162461bcd60e51b815260206004820152600f60248201527f496e76616c6964207265766f6b652100000000000000000000000000000000006044820152606401610713565b60018260030160008282546111ff9190611cfd565b909155505080546001908290600090611219908490611cfd565b909155506001979650505050505050565b60008061123684611661565b600081815260046020908152604080832054600154845260029092528220929350919060038161126d6101008a0160e08b016118e1565b6001600160a01b031681526020808201929092526040908101600090812060015482528352818120878252909252902082549091504210156112f15760405162461bcd60e51b815260206004820152601260248201527f536561736f6e206e6f74207374617274656400000000000000000000000000006044820152606401610713565b816001015442106113445760405162461bcd60e51b815260206004820152601460248201527f536561736f6e20616c726561647920656e6465640000000000000000000000006044820152606401610713565b600083116113945760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420766f756368206461746100000000000000000000000000006044820152606401610713565b81600201548260030154106113eb5760405162461bcd60e51b815260206004820152601960248201527f536561736f6e206d617820766f756368657320726561636821000000000000006044820152606401610713565b8054831161143b5760405162461bcd60e51b815260206004820152601260248201527f4d617820766f75636865732072656163682100000000000000000000000000006044820152606401610713565b60018260030160008282546114509190611d10565b90915550508054600190829060009061146a908490611d10565b90915550504260018281019190915560029091019290925550949350505050565b6000808260405160200161149f9190611d23565b60405160208183030381529060405290506020815111156115025760405162461bcd60e51b815260206004820152601260248201527f537472696e6720697320746f6f206c6f6e6700000000000000000000000000006044820152606401610713565b6020015192915050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661088c5761153d8161168e565b6115488360206116a0565b604051602001611559929190611d35565b60408051601f198184030181529082905262461bcd60e51b825261071391600401611998565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106115c8577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106115f4576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061161257662386f26fc10000830492506010015b6305f5e100831061162a576305f5e100830492506008015b612710831061163e57612710830492506004015b60648310611650576064830492506002015b600a83106106a65760010192915050565b6000611671610120830183611db6565b60405161167f929190611dfd565b60405180910390209050919050565b60606106a66001600160a01b03831660145b606060006116af836002611e0d565b6116ba906002611d10565b67ffffffffffffffff8111156116d2576116d2611adc565b6040519080825280601f01601f1916602001820160405280156116fc576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061173357611733611cb0565b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061177e5761177e611cb0565b60200101906001600160f81b031916908160001a90535060006117a2846002611e0d565b6117ad906001611d10565b90505b6001811115611832577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106117ee576117ee611cb0565b1a60f81b82828151811061180457611804611cb0565b60200101906001600160f81b031916908160001a90535060049490941c9361182b81611e24565b90506117b0565b5083156118815760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610713565b9392505050565b60006020828403121561189a57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461188157600080fd5b80356001600160a01b0381168114610e3b57600080fd5b6000602082840312156118f357600080fd5b611881826118ca565b60006020828403121561190e57600080fd5b5035919050565b6000806040838503121561192857600080fd5b82359150611938602084016118ca565b90509250929050565b60008060006060848603121561195657600080fd5b61195f846118ca565b95602085013595506040909401359392505050565b60005b8381101561198f578181015183820152602001611977565b50506000910152565b60208152600082518060208401526119b7816040850160208701611974565b601f01601f19169190910160400192915050565b600080604083850312156119de57600080fd5b50508035926020909101359150565b60008060008060808587031215611a0357600080fd5b5050823594602084013594506040840135936060013592509050565b60008083601f840112611a3157600080fd5b50813567ffffffffffffffff811115611a4957600080fd5b6020830191508360208260051b8501011115611a6457600080fd5b9250929050565b60008060008060408587031215611a8157600080fd5b843567ffffffffffffffff811115611a9857600080fd5b611aa487828801611a1f565b909550935050602085013567ffffffffffffffff811115611ac457600080fd5b611ad087828801611a1f565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611b0357600080fd5b813567ffffffffffffffff811115611b1d57611b1d611adc565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b4c57611b4c611adc565b604052818152838201602001851015611b6457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215611b9657600080fd5b833567ffffffffffffffff811115611bad57600080fd5b611bb986828701611af2565b935050602084013567ffffffffffffffff811115611bd657600080fd5b611be286828701611af2565b925050604084013567ffffffffffffffff811115611bff57600080fd5b611c0b86828701611af2565b9150509250925092565b600060208284031215611c2757600080fd5b813567ffffffffffffffff811115611c3e57600080fd5b8201610140818503121561188157600080fd5b60008451611c63818460208901611974565b601760f91b9083019081528451611c81816001840160208901611974565b601760f91b600192909101918201528351611ca3816002840160208801611974565b0160020195945050505050565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112611cdd57600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156106a6576106a6611ce7565b808201808211156106a6576106a6611ce7565b60008251611cdd818460208701611974565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d6d816017850160208801611974565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611daa816028840160208801611974565b01602801949350505050565b6000808335601e19843603018112611dcd57600080fd5b83018035915067ffffffffffffffff821115611de857600080fd5b602001915036819003821315611a6457600080fd5b8183823760009101908152919050565b80820281158282048414176106a6576106a6611ce7565b600081611e3357611e33611ce7565b50600019019056fea264697066735822122008bd62048e19fa11ec183614fa6d45ce9e035740c2905184f4d69ac2a9198b2c64736f6c634300081a0033a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177500000000000000000000000042000000000000000000000000000000000000210000000000000000000000009475a4c1bf5fc80ae079303f14b523da19619c16
Deployed Bytecode
0x6080604052600436106101b05760003560e01c806391d14854116100ec578063d547741f1161008a578063e4e81b8011610064578063e4e81b801461053b578063e60c35051461059f578063ec87621c146105b2578063f8f71a76146105e657600080fd5b8063d547741f146104e8578063d6fb7d7914610508578063e49617e11461052857600080fd5b8063ac18de43116100c6578063ac18de431461047e578063bcb396211461049e578063ce46e046146104b4578063d27428f6146104c857600080fd5b806391d148541461041257806391db0b7e14610456578063a217fddf1461046957600080fd5b806349ebb4181161015957806375b238fc1161013357806375b238fc1461038b5780637e6a7e00146103bf578063829efc28146103df57806388e5b2d9146103ff57600080fd5b806349ebb418146102e157806354fd4d5014610349578063704802751461036b57600080fd5b80632d06177a1161018a5780632d06177a146102815780632f2ff15d146102a157806336568abe146102c157600080fd5b806301ffc9a7146101ee5780631785f53c14610223578063248a9ca31461024357600080fd5b366101e9576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b600080fd5b3480156101fa57600080fd5b5061020e610209366004611888565b610613565b60405190151581526020015b60405180910390f35b34801561022f57600080fd5b506101e761023e3660046118e1565b6106ac565b34801561024f57600080fd5b5061027361025e3660046118fc565b60009081526020819052604090206001015490565b60405190815260200161021a565b34801561028d57600080fd5b506101e761029c3660046118e1565b610749565b3480156102ad57600080fd5b506101e76102bc366004611915565b6107da565b3480156102cd57600080fd5b506101e76102dc366004611915565b610804565b3480156102ed57600080fd5b5061032e6102fc366004611941565b600360209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161021a565b34801561035557600080fd5b5061035e610890565b60405161021a9190611998565b34801561037757600080fd5b506101e76103863660046118e1565b610933565b34801561039757600080fd5b506102737fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156103cb57600080fd5b506101e76103da3660046119cb565b6109c8565b3480156103eb57600080fd5b506101e76103fa3660046119ed565b610a47565b61020e61040d366004611a6b565b610b07565b34801561041e57600080fd5b5061020e61042d366004611915565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61020e610464366004611a6b565b610bd6565b34801561047557600080fd5b50610273600081565b34801561048a57600080fd5b506101e76104993660046118e1565b610c95565b3480156104aa57600080fd5b5061027360015481565b3480156104c057600080fd5b50600061020e565b3480156104d457600080fd5b506102736104e3366004611b81565b610d2a565b3480156104f457600080fd5b506101e7610503366004611915565b610d90565b34801561051457600080fd5b506101e76105233660046118fc565b610db5565b61020e610536366004611c15565b610e27565b34801561054757600080fd5b5061057f6105563660046118fc565b600260208190526000918252604090912080546001820154928201546003909201549092919084565b60408051948552602085019390935291830152606082015260800161021a565b61020e6105ad366004611c15565b610e40565b3480156105be57600080fd5b506102737f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b3480156105f257600080fd5b506102736106013660046118fc565b60046020526000908152604090205481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806106a657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff1661071c5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b60448201526064015b60405180910390fd5b6107467fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177582610d90565b50565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff166107b45760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08825b6000828152602081905260409020600101546107f581610e54565b6107ff8383610e5e565b505050565b6001600160a01b03811633146108825760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610713565b61088c8282610efc565b5050565b60606108bb7f0000000000000000000000000000000000000000000000000000000000000001610f7b565b6108e47f0000000000000000000000000000000000000000000000000000000000000003610f7b565b61090d7f0000000000000000000000000000000000000000000000000000000000000000610f7b565b60405160200161091f93929190611c51565b604051602081830303815290604052905090565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff1661099e5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775826107da565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610a355760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b60009182526004602052604090912055565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610ab45760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b604080516080810182529384526020808501938452848201928352600086815260028083529281206003810180546060890190815298909252918390529451815592516001840155905191015590519055565b6000610b1161101b565b83828114610b325760405163251f56a160e21b815260040160405180910390fd5b3460005b82811015610bc6576000868683818110610b5257610b52611cb0565b90506020020135905082811115610b7c5760405163044044a560e21b815260040160405180910390fd5b610ba9898984818110610b9157610b91611cb0565b9050602002810190610ba39190611cc6565b8261107f565b610bba576000945050505050610bce565b90910390600101610b36565b506001925050505b949350505050565b6000610be061101b565b83828114610c015760405163251f56a160e21b815260040160405180910390fd5b3460005b82811015610bc6576000868683818110610c2157610c21611cb0565b90506020020135905082811115610c4b5760405163044044a560e21b815260040160405180910390fd5b610c78898984818110610c6057610c60611cb0565b9050602002810190610c729190611cc6565b8261122a565b610c89576000945050505050610bce565b90910390600101610c05565b3360009081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec602052604090205460ff16610d005760405162461bcd60e51b815260206004820152600a60248201526927b7363c9020b236b4b760b11b6044820152606401610713565b6107467f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0882610d90565b600080610d368561148b565b90506000610d438561148b565b90506000610d508561148b565b6040805160208101869052908101849052606081018290529091506080016040516020818303038152906040528051906020012093505050509392505050565b600082815260208190526040902060010154610dab81610e54565b6107ff8383610efc565b3360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16610e225760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9026b0b730b3b2b960a11b6044820152606401610713565b600155565b6000610e3161101b565b6106a6823461107f565b919050565b6000610e4a61101b565b6106a6823461122a565b610746813361150c565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661088c576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610eb83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff161561088c576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606000610f888361157f565b600101905060008167ffffffffffffffff811115610fa857610fa8611adc565b6040519080825280601f01601f191660200182016040528015610fd2576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610fdc57509392505050565b336001600160a01b037f0000000000000000000000004200000000000000000000000000000000000021161461107d576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008061108b84611661565b60015460009081526002602052604081209192506003816110b3610100890160e08a016118e1565b6001600160a01b031681526020808201929092526040908101600090812060015482528352818120868252909252902082549091504210156111375760405162461bcd60e51b815260206004820152601260248201527f536561736f6e206e6f74207374617274656400000000000000000000000000006044820152606401610713565b8160010154421061118a5760405162461bcd60e51b815260206004820152601460248201527f536561736f6e20616c726561647920656e6465640000000000000000000000006044820152606401610713565b80541580159061119e575060008260030154115b6111ea5760405162461bcd60e51b815260206004820152600f60248201527f496e76616c6964207265766f6b652100000000000000000000000000000000006044820152606401610713565b60018260030160008282546111ff9190611cfd565b909155505080546001908290600090611219908490611cfd565b909155506001979650505050505050565b60008061123684611661565b600081815260046020908152604080832054600154845260029092528220929350919060038161126d6101008a0160e08b016118e1565b6001600160a01b031681526020808201929092526040908101600090812060015482528352818120878252909252902082549091504210156112f15760405162461bcd60e51b815260206004820152601260248201527f536561736f6e206e6f74207374617274656400000000000000000000000000006044820152606401610713565b816001015442106113445760405162461bcd60e51b815260206004820152601460248201527f536561736f6e20616c726561647920656e6465640000000000000000000000006044820152606401610713565b600083116113945760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420766f756368206461746100000000000000000000000000006044820152606401610713565b81600201548260030154106113eb5760405162461bcd60e51b815260206004820152601960248201527f536561736f6e206d617820766f756368657320726561636821000000000000006044820152606401610713565b8054831161143b5760405162461bcd60e51b815260206004820152601260248201527f4d617820766f75636865732072656163682100000000000000000000000000006044820152606401610713565b60018260030160008282546114509190611d10565b90915550508054600190829060009061146a908490611d10565b90915550504260018281019190915560029091019290925550949350505050565b6000808260405160200161149f9190611d23565b60405160208183030381529060405290506020815111156115025760405162461bcd60e51b815260206004820152601260248201527f537472696e6720697320746f6f206c6f6e6700000000000000000000000000006044820152606401610713565b6020015192915050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661088c5761153d8161168e565b6115488360206116a0565b604051602001611559929190611d35565b60408051601f198184030181529082905262461bcd60e51b825261071391600401611998565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106115c8577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106115f4576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061161257662386f26fc10000830492506010015b6305f5e100831061162a576305f5e100830492506008015b612710831061163e57612710830492506004015b60648310611650576064830492506002015b600a83106106a65760010192915050565b6000611671610120830183611db6565b60405161167f929190611dfd565b60405180910390209050919050565b60606106a66001600160a01b03831660145b606060006116af836002611e0d565b6116ba906002611d10565b67ffffffffffffffff8111156116d2576116d2611adc565b6040519080825280601f01601f1916602001820160405280156116fc576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061173357611733611cb0565b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061177e5761177e611cb0565b60200101906001600160f81b031916908160001a90535060006117a2846002611e0d565b6117ad906001611d10565b90505b6001811115611832577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106117ee576117ee611cb0565b1a60f81b82828151811061180457611804611cb0565b60200101906001600160f81b031916908160001a90535060049490941c9361182b81611e24565b90506117b0565b5083156118815760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610713565b9392505050565b60006020828403121561189a57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461188157600080fd5b80356001600160a01b0381168114610e3b57600080fd5b6000602082840312156118f357600080fd5b611881826118ca565b60006020828403121561190e57600080fd5b5035919050565b6000806040838503121561192857600080fd5b82359150611938602084016118ca565b90509250929050565b60008060006060848603121561195657600080fd5b61195f846118ca565b95602085013595506040909401359392505050565b60005b8381101561198f578181015183820152602001611977565b50506000910152565b60208152600082518060208401526119b7816040850160208701611974565b601f01601f19169190910160400192915050565b600080604083850312156119de57600080fd5b50508035926020909101359150565b60008060008060808587031215611a0357600080fd5b5050823594602084013594506040840135936060013592509050565b60008083601f840112611a3157600080fd5b50813567ffffffffffffffff811115611a4957600080fd5b6020830191508360208260051b8501011115611a6457600080fd5b9250929050565b60008060008060408587031215611a8157600080fd5b843567ffffffffffffffff811115611a9857600080fd5b611aa487828801611a1f565b909550935050602085013567ffffffffffffffff811115611ac457600080fd5b611ad087828801611a1f565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611b0357600080fd5b813567ffffffffffffffff811115611b1d57611b1d611adc565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b4c57611b4c611adc565b604052818152838201602001851015611b6457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215611b9657600080fd5b833567ffffffffffffffff811115611bad57600080fd5b611bb986828701611af2565b935050602084013567ffffffffffffffff811115611bd657600080fd5b611be286828701611af2565b925050604084013567ffffffffffffffff811115611bff57600080fd5b611c0b86828701611af2565b9150509250925092565b600060208284031215611c2757600080fd5b813567ffffffffffffffff811115611c3e57600080fd5b8201610140818503121561188157600080fd5b60008451611c63818460208901611974565b601760f91b9083019081528451611c81816001840160208901611974565b601760f91b600192909101918201528351611ca3816002840160208801611974565b0160020195945050505050565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112611cdd57600080fd5b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156106a6576106a6611ce7565b808201808211156106a6576106a6611ce7565b60008251611cdd818460208701611974565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611d6d816017850160208801611974565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611daa816028840160208801611974565b01602801949350505050565b6000808335601e19843603018112611dcd57600080fd5b83018035915067ffffffffffffffff821115611de857600080fd5b602001915036819003821315611a6457600080fd5b8183823760009101908152919050565b80820281158282048414176106a6576106a6611ce7565b600081611e3357611e33611ce7565b50600019019056fea264697066735822122008bd62048e19fa11ec183614fa6d45ce9e035740c2905184f4d69ac2a9198b2c64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000042000000000000000000000000000000000000210000000000000000000000009475a4c1bf5fc80ae079303f14b523da19619c16
-----Decoded View---------------
Arg [0] : eas (address): 0x4200000000000000000000000000000000000021
Arg [1] : initialAdmin (address): 0x9475A4C1BF5Fc80aE079303f14B523da19619c16
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004200000000000000000000000000000000000021
Arg [1] : 0000000000000000000000009475a4c1bf5fc80ae079303f14b523da19619c16
Loading...
Loading
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.