Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0xcfa14081cb5744fb8ef87694ec172605b92bbf33e0122dcbaa2050e1c8f841fd | - | (pending) | 2 hrs ago | IN | 0 ETH | (Pending) | |||
Attest By Delega... | 12846272 | 92 days ago | IN | 0 ETH | 0.00005635 | ||||
Attest By Delega... | 12845724 | 92 days ago | IN | 0 ETH | 0.00022227 | ||||
Attest By Delega... | 12771782 | 95 days ago | IN | 0 ETH | 0.00004718 | ||||
Attest By Delega... | 12628783 | 101 days ago | IN | 0 ETH | 0.00002033 | ||||
Attest By Delega... | 12502862 | 106 days ago | IN | 0 ETH | 0.00004074 | ||||
Attest By Delega... | 12471431 | 107 days ago | IN | 0 ETH | 0.00003081 | ||||
Attest By Delega... | 12442204 | 108 days ago | IN | 0 ETH | 0.0000244 | ||||
Attest By Delega... | 12410162 | 110 days ago | IN | 0 ETH | 0.00002119 | ||||
Attest By Delega... | 12328587 | 113 days ago | IN | 0 ETH | 0.00014593 | ||||
Attest By Delega... | 12307313 | 114 days ago | IN | 0 ETH | 0.00003445 | ||||
Attest By Delega... | 12165610 | 119 days ago | IN | 0 ETH | 0.0000248 | ||||
Attest By Delega... | 12156541 | 120 days ago | IN | 0 ETH | 0.0000306 | ||||
Attest By Delega... | 12117487 | 121 days ago | IN | 0 ETH | 0.0000294 | ||||
Attest By Delega... | 12098613 | 122 days ago | IN | 0 ETH | 0.00002543 | ||||
Attest By Delega... | 12043856 | 124 days ago | IN | 0 ETH | 0.0000586 | ||||
Attest By Delega... | 11992569 | 126 days ago | IN | 0 ETH | 0.00003029 | ||||
Attest By Delega... | 11907022 | 129 days ago | IN | 0 ETH | 0.00003702 | ||||
Attest By Delega... | 11882852 | 130 days ago | IN | 0 ETH | 0.00002458 | ||||
Attest By Delega... | 11882852 | 130 days ago | IN | 0 ETH | 0.00002474 | ||||
Attest By Delega... | 11816129 | 132 days ago | IN | 0 ETH | 0.00004901 | ||||
Attest By Delega... | 11801312 | 133 days ago | IN | 0 ETH | 0.0000262 | ||||
Attest By Delega... | 11759100 | 135 days ago | IN | 0 ETH | 0.00002853 | ||||
Attest By Delega... | 11755488 | 135 days ago | IN | 0 ETH | 0.00005836 | ||||
Attest By Delega... | 11748211 | 135 days ago | IN | 0 ETH | 0.00004572 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
AttesterProxy
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19 <=0.8.26; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import "@ethereum-attestation-service/eas-contracts/contracts/eip712/proxy/EIP712Proxy.sol"; import "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol"; /// @title AttesterProxy /// @notice An EIP712 proxy that allows only specific addresses to attest. /// Based on PermissionedEIP712Proxy in the EAS repo. contract AttesterProxy is EIP712Proxy, Ownable { // The global EAS contract. IEAS private immutable _eas; // Authorized badge attester accounts. mapping(address => bool) public isAttester; /// @dev Creates a new PermissionedEIP712Proxy instance. /// @param eas The address of the global EAS contract. constructor(IEAS eas) EIP712Proxy(eas, "AttesterProxy") Ownable(msg.sender) { _eas = eas; } /// @notice Enables or disables a given attester. /// @param attester The attester address. /// @param enable True if enable, false if disable. function toggleAttester(address attester, bool enable) external onlyOwner { isAttester[attester] = enable; } /// @inheritdoc EIP712Proxy function attestByDelegation(DelegatedProxyAttestationRequest calldata delegatedRequest) public payable override returns (bytes32) { // Ensure that only the owner is allowed to delegate attestations. _verifyAttester(delegatedRequest.attester); // Ensure that only the recipient can submit delegated attestation transactions. if (msg.sender != delegatedRequest.data.recipient) { revert AccessDenied(); } return super.attestByDelegation(delegatedRequest); } /// @notice Create attestation through the proxy. /// @param request The arguments of the attestation request. /// @return The UID of the new attestation. function attest(AttestationRequest calldata request) external returns (bytes32) { _verifyAttester(msg.sender); return _eas.attest(request); } /// @notice Revoke attestation through the proxy. /// @param request The arguments of the revocation request. function revoke(RevocationRequest calldata request) external { _verifyAttester(msg.sender); _eas.revoke(request); } /// @dev Ensures that only the allowed attester can attest. /// @param attester The attester to verify. function _verifyAttester(address attester) private view { if (!isAttester[attester]) { revert AccessDenied(); } } }
// 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.26; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; // prettier-ignore import { AccessDenied, DeadlineExpired, Signature, InvalidEAS, InvalidLength, InvalidSignature, NotFound, NO_EXPIRATION_TIME, uncheckedInc } from "../../Common.sol"; // prettier-ignore import { AttestationRequest, AttestationRequestData, IEAS, MultiAttestationRequest, MultiRevocationRequest, RevocationRequest, RevocationRequestData } from "../../IEAS.sol"; import { Semver } from "../../Semver.sol"; /// @notice A struct representing the full arguments of the full delegated attestation request. struct DelegatedProxyAttestationRequest { bytes32 schema; // The unique identifier of the schema. AttestationRequestData data; // The arguments of the attestation request. Signature signature; // The EIP712 signature data. address attester; // The attesting account. uint64 deadline; // The deadline of the signature/request. } /// @notice A struct representing the full arguments of the delegated multi attestation request. struct MultiDelegatedProxyAttestationRequest { bytes32 schema; // The unique identifier of the schema. AttestationRequestData[] data; // The arguments of the attestation requests. Signature[] signatures; // The EIP712 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 full delegated revocation request. struct DelegatedProxyRevocationRequest { bytes32 schema; // The unique identifier of the schema. RevocationRequestData data; // The arguments of the revocation request. Signature signature; // The EIP712 signature data. address revoker; // The revoking account. uint64 deadline; // The deadline of the signature/request. } /// @notice A struct representing the full arguments of the delegated multi revocation request. struct MultiDelegatedProxyRevocationRequest { bytes32 schema; // The unique identifier of the schema. RevocationRequestData[] data; // The arguments of the revocation requests. Signature[] signatures; // The EIP712 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 EIP712Proxy /// @notice This utility contract an be used to aggregate delegated attestations without requiring a specific order via /// nonces. The contract doesn't request nonces and implements replay protection by storing ***immalleable*** /// signatures. contract EIP712Proxy is Semver, EIP712 { error UsedSignature(); // The hash of the data type used to relay calls to the attest function. It's the value of // keccak256("Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 value,uint64 deadline)"). bytes32 private constant ATTEST_PROXY_TYPEHASH = 0xea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af1; // The hash of the data type used to relay calls to the revoke function. It's the value of // keccak256("Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint64 deadline)"). bytes32 private constant REVOKE_PROXY_TYPEHASH = 0x78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d; // The global EAS contract. IEAS private immutable _eas; // The user readable name of the signing domain. string private _name; // The global mapping between proxy attestations and their attesters, so that we can verify that only the original // attester is able to revert attestations by proxy. mapping(bytes32 uid => address attester) private _attesters; // Replay protection signatures. mapping(bytes signature => bool used) private _signatures; /// @dev Creates a new EIP1271Verifier instance. /// @param eas The address of the global EAS contract. /// @param name The user readable name of the signing domain. constructor(IEAS eas, string memory name) Semver(1, 3, 0) EIP712(name, "1.3.0") { if (address(eas) == address(0)) { revert InvalidEAS(); } _eas = eas; _name = name; } /// @notice Returns the EAS. function getEAS() external view returns (IEAS) { return _eas; } /// @notice Returns the domain separator used in the encoding of the signatures for attest, and revoke. function getDomainSeparator() external view returns (bytes32) { return _domainSeparatorV4(); } /// Returns the EIP712 type hash for the attest function. function getAttestTypeHash() external pure returns (bytes32) { return ATTEST_PROXY_TYPEHASH; } /// Returns the EIP712 type hash for the revoke function. function getRevokeTypeHash() external pure returns (bytes32) { return REVOKE_PROXY_TYPEHASH; } /// Returns the EIP712 name. function getName() external view returns (string memory) { return _name; } /// Returns the attester for a given uid. function getAttester(bytes32 uid) external view returns (address) { return _attesters[uid]; } /// @notice Attests to a specific schema via the provided EIP712 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( DelegatedProxyAttestationRequest calldata delegatedRequest ) public payable virtual returns (bytes32) { _verifyAttest(delegatedRequest); bytes32 uid = _eas.attest{ value: msg.value }( AttestationRequest({ schema: delegatedRequest.schema, data: delegatedRequest.data }) ); _attesters[uid] = delegatedRequest.attester; return uid; } /// @notice Attests to multiple schemas using via provided EIP712 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( MultiDelegatedProxyAttestationRequest[] calldata multiDelegatedRequests ) public payable virtual returns (bytes32[] memory) { uint256 length = multiDelegatedRequests.length; MultiAttestationRequest[] memory multiRequests = new MultiAttestationRequest[](length); for (uint256 i = 0; i < length; i = uncheckedInc(i)) { MultiDelegatedProxyAttestationRequest calldata multiDelegatedRequest = multiDelegatedRequests[i]; AttestationRequestData[] calldata data = multiDelegatedRequest.data; // Ensure that no inputs are missing. uint256 dataLength = data.length; if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) { revert InvalidLength(); } // Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing nonces. for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) { _verifyAttest( DelegatedProxyAttestationRequest({ schema: multiDelegatedRequest.schema, data: data[j], signature: multiDelegatedRequest.signatures[j], attester: multiDelegatedRequest.attester, deadline: multiDelegatedRequest.deadline }) ); } multiRequests[i] = MultiAttestationRequest({ schema: multiDelegatedRequest.schema, data: data }); } bytes32[] memory uids = _eas.multiAttest{ value: msg.value }(multiRequests); // Store all attesters, according to the order of the attestation requests. uint256 uidCounter = 0; for (uint256 i = 0; i < length; i = uncheckedInc(i)) { MultiDelegatedProxyAttestationRequest calldata multiDelegatedRequest = multiDelegatedRequests[i]; AttestationRequestData[] calldata data = multiDelegatedRequest.data; uint256 dataLength = data.length; for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) { _attesters[uids[uidCounter]] = multiDelegatedRequest.attester; unchecked { ++uidCounter; } } } return uids; } /// @notice Revokes an existing attestation to a specific schema via the provided EIP712 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(DelegatedProxyRevocationRequest calldata delegatedRequest) public payable virtual { _verifyRevoke(delegatedRequest); return _eas.revoke{ value: msg.value }( RevocationRequest({ schema: delegatedRequest.schema, data: delegatedRequest.data }) ); } /// @notice Revokes existing attestations to multiple schemas via provided EIP712 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( MultiDelegatedProxyRevocationRequest[] calldata multiDelegatedRequests ) public payable virtual { uint256 length = multiDelegatedRequests.length; MultiRevocationRequest[] memory multiRequests = new MultiRevocationRequest[](length); for (uint256 i = 0; i < length; i = uncheckedInc(i)) { MultiDelegatedProxyRevocationRequest memory multiDelegatedRequest = multiDelegatedRequests[i]; RevocationRequestData[] memory data = multiDelegatedRequest.data; // Ensure that no inputs are missing. uint256 dataLength = data.length; if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) { revert InvalidLength(); } // Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing nonces. for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) { RevocationRequestData memory requestData = data[j]; _verifyRevoke( DelegatedProxyRevocationRequest({ schema: multiDelegatedRequest.schema, data: requestData, signature: multiDelegatedRequest.signatures[j], revoker: multiDelegatedRequest.revoker, deadline: multiDelegatedRequest.deadline }) ); } multiRequests[i] = MultiRevocationRequest({ schema: multiDelegatedRequest.schema, data: data }); } _eas.multiRevoke{ value: msg.value }(multiRequests); } /// @dev Verifies delegated attestation request. /// @param request The arguments of the delegated attestation request. function _verifyAttest(DelegatedProxyAttestationRequest memory request) internal { if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) { revert DeadlineExpired(); } AttestationRequestData memory data = request.data; Signature memory signature = request.signature; _verifyUnusedSignature(signature); bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( ATTEST_PROXY_TYPEHASH, request.attester, request.schema, data.recipient, data.expirationTime, data.revocable, data.refUID, keccak256(data.data), data.value, request.deadline ) ) ); if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.attester) { revert InvalidSignature(); } } /// @dev Verifies delegated revocation request. /// @param request The arguments of the delegated revocation request. function _verifyRevoke(DelegatedProxyRevocationRequest memory request) internal { if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) { revert DeadlineExpired(); } RevocationRequestData memory data = request.data; // Allow only original attesters to revoke their attestations. address attester = _attesters[data.uid]; if (attester == address(0)) { revert NotFound(); } if (attester != msg.sender) { revert AccessDenied(); } Signature memory signature = request.signature; _verifyUnusedSignature(signature); bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( REVOKE_PROXY_TYPEHASH, request.revoker, request.schema, data.uid, data.value, request.deadline ) ) ); if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.revoker) { revert InvalidSignature(); } } /// @dev Ensures that the provided EIP712 signature wasn't already used. /// @param signature The EIP712 signature data. function _verifyUnusedSignature(Signature memory signature) internal { bytes memory packedSignature = abi.encodePacked(signature.v, signature.r, signature.s); if (_signatures[packedSignature]) { revert UsedSignature(); } _signatures[packedSignature] = true; } /// @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the /// current block time. function _time() internal view virtual returns (uint64) { return uint64(block.timestamp); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { 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 { 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 v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; import {MessageHashUtils} from "./MessageHashUtils.sol"; import {ShortStrings, ShortString} from "../ShortStrings.sol"; import {IERC5267} from "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * @custom:oz-upgrades-unsafe-allow state-variable-immutable */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: By default this function reads _name which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { return _name.toStringWithFallback(_nameFallback); } /** * @dev The version parameter for the EIP712 domain. * * NOTE: By default this function reads _version which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { return _version.toStringWithFallback(_versionFallback); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (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 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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 (unsignedRoundsUp(rounding) && 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 * towards zero. * * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; import {StorageSlot} from "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using * {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @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), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @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) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } 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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IEAS","name":"eas","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"InvalidEAS","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"UsedSignature","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData","name":"data","type":"tuple"}],"internalType":"struct AttestationRequest","name":"request","type":"tuple"}],"name":"attest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData","name":"data","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature","name":"signature","type":"tuple"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct DelegatedProxyAttestationRequest","name":"delegatedRequest","type":"tuple"}],"name":"attestByDelegation","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAttestTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"uid","type":"bytes32"}],"name":"getAttester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEAS","outputs":[{"internalType":"contract IEAS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRevokeTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAttester","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AttestationRequestData[]","name":"data","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"signatures","type":"tuple[]"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct MultiDelegatedProxyAttestationRequest[]","name":"multiDelegatedRequests","type":"tuple[]"}],"name":"multiAttestByDelegation","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData[]","name":"data","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"signatures","type":"tuple[]"},{"internalType":"address","name":"revoker","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct MultiDelegatedProxyRevocationRequest[]","name":"multiDelegatedRequests","type":"tuple[]"}],"name":"multiRevokeByDelegation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData","name":"data","type":"tuple"}],"internalType":"struct RevocationRequest","name":"request","type":"tuple"}],"name":"revoke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"schema","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct RevocationRequestData","name":"data","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature","name":"signature","type":"tuple"},{"internalType":"address","name":"revoker","type":"address"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"internalType":"struct DelegatedProxyRevocationRequest","name":"delegatedRequest","type":"tuple"}],"name":"revokeByDelegation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"toggleAttester","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
61020060405234801561001157600080fd5b50604051614e61380380614e6183398181016040528101906100339190610533565b33816040518060400160405280600d81526020017f417474657374657250726f787900000000000000000000000000000000000000815250806040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525060016003600082608081815250508160a081815250508060c081815250505050506100d76000836102da60201b90919060201c565b61018081815250506100f36001826102da60201b90919060201c565b6101a08181525050818051906020012061014081815250508080519060200120610160818152505046610100818152505061013261032a60201b60201c565b60e081815250503073ffffffffffffffffffffffffffffffffffffffff166101208173ffffffffffffffffffffffffffffffffffffffff16815250505050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101d6576040517f83780ffe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166101c08173ffffffffffffffffffffffffffffffffffffffff1681525050806002908161021a91906107b0565b505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361028f5760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016102869190610891565b60405180910390fd5b61029e8161038660201b60201c565b508073ffffffffffffffffffffffffffffffffffffffff166101e08173ffffffffffffffffffffffffffffffffffffffff168152505050610a65565b60006020835110156102fc576102f58361044c60201b60201c565b9050610324565b8261030c836104b460201b60201c565b600001908161031b91906107b0565b5060ff60001b90505b92915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6101405161016051463060405160200161036b9594939291906108d4565b60405160208183030381529060405280519060200120905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080829050601f8151111561049957826040517f305a27a900000000000000000000000000000000000000000000000000000000815260040161049091906109ac565b60405180910390fd5b8051816104a5906109fe565b60001c1760001b915050919050565b6000819050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104ee826104c3565b9050919050565b6000610500826104e3565b9050919050565b610510816104f5565b811461051b57600080fd5b50565b60008151905061052d81610507565b92915050565b600060208284031215610549576105486104be565b5b60006105578482850161051e565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806105e157607f821691505b6020821081036105f4576105f361059a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261065c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261061f565b610666868361061f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006106ad6106a86106a38461067e565b610688565b61067e565b9050919050565b6000819050919050565b6106c783610692565b6106db6106d3826106b4565b84845461062c565b825550505050565b600090565b6106f06106e3565b6106fb8184846106be565b505050565b5b8181101561071f576107146000826106e8565b600181019050610701565b5050565b601f82111561076457610735816105fa565b61073e8461060f565b8101602085101561074d578190505b6107616107598561060f565b830182610700565b50505b505050565b600082821c905092915050565b600061078760001984600802610769565b1980831691505092915050565b60006107a08383610776565b9150826002028217905092915050565b6107b982610560565b67ffffffffffffffff8111156107d2576107d161056b565b5b6107dc82546105c9565b6107e7828285610723565b600060209050601f83116001811461081a5760008415610808578287015190505b6108128582610794565b86555061087a565b601f198416610828866105fa565b60005b828110156108505784890151825560018201915060208501945060208101905061082b565b8683101561086d5784890151610869601f891682610776565b8355505b6001600288020188555050505b505050505050565b61088b816104e3565b82525050565b60006020820190506108a66000830184610882565b92915050565b6000819050919050565b6108bf816108ac565b82525050565b6108ce8161067e565b82525050565b600060a0820190506108e960008301886108b6565b6108f660208301876108b6565b61090360408301866108b6565b61091060608301856108c5565b61091d6080830184610882565b9695505050505050565b600082825260208201905092915050565b60005b8381101561095657808201518184015260208101905061093b565b60008484015250505050565b6000601f19601f8301169050919050565b600061097e82610560565b6109888185610927565b9350610998818560208601610938565b6109a181610962565b840191505092915050565b600060208201905081810360008301526109c68184610973565b905092915050565b600081519050919050565b6000819050602082019050919050565b60006109f582516108ac565b80915050919050565b6000610a09826109ce565b82610a13846109d9565b9050610a1e816109e9565b92506020821015610a5e57610a597fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261061f565b831692505b5050919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051614348610b19600039600081816108fc015261108901526000818161065101528181610a2f01528181610d9801528181610f6a015261157d0152600061188f0152600061185401526000611e9f01526000611e7e01526000611a7701526000611acd01526000611af6015260006109e1015260006109b80152600061098f01526143486000f3fe6080604052600436106101145760003560e01c8063715018a6116100a0578063b6ebe53911610064578063b6ebe5391461035f578063b83010d31461039c578063ed24911d146103c7578063f17325e7146103f2578063f2fde38b1461042f57610114565b8063715018a6146102a057806384b0196e146102b75780638da5cb5b146102e85780639541152514610313578063a6d4dbc71461034357610114565b806317d7de7c116100e757806317d7de7c146101c65780633c042715146101f1578063469262671461022157806354fd4d501461024a57806365c40b9c1461027557610114565b80630eabf660146101195780630ee489481461013557806310d736d51461015e57806312b11a171461019b575b600080fd5b610133600480360381019061012e91906122ff565b610458565b005b34801561014157600080fd5b5061015c600480360381019061015791906123e2565b6106e1565b005b34801561016a57600080fd5b5061018560048036038101906101809190612458565b610744565b6040516101929190612494565b60405180910390f35b3480156101a757600080fd5b506101b0610781565b6040516101bd91906124be565b60405180910390f35b3480156101d257600080fd5b506101db6107ac565b6040516101e89190612569565b60405180910390f35b61020b600480360381019061020691906125af565b61083e565b60405161021891906124be565b60405180910390f35b34801561022d57600080fd5b5061024860048036038101906102439190612617565b6108f1565b005b34801561025657600080fd5b5061025f610988565b60405161026c9190612569565b60405180910390f35b34801561028157600080fd5b5061028a610a2b565b60405161029791906126a3565b60405180910390f35b3480156102ac57600080fd5b506102b5610a53565b005b3480156102c357600080fd5b506102cc610a67565b6040516102df97969594939291906127d0565b60405180910390f35b3480156102f457600080fd5b506102fd610b11565b60405161030a9190612494565b60405180910390f35b61032d600480360381019061032891906128aa565b610b3b565b60405161033a91906129b5565b60405180910390f35b61035d600480360381019061035891906129f7565b610f4f565b005b34801561036b57600080fd5b5061038660048036038101906103819190612a25565b611022565b6040516103939190612a61565b60405180910390f35b3480156103a857600080fd5b506103b1611042565b6040516103be91906124be565b60405180910390f35b3480156103d357600080fd5b506103dc61106d565b6040516103e991906124be565b60405180910390f35b3480156103fe57600080fd5b5061041960048036038101906104149190612a9b565b61107c565b60405161042691906124be565b60405180910390f35b34801561043b57600080fd5b5061045660048036038101906104519190612a25565b61112a565b005b600082829050905060008167ffffffffffffffff81111561047c5761047b612ae4565b5b6040519080825280602002602001820160405280156104b557816020015b6104a261224c565b81526020019060019003908161049a5790505b50905060005b8281101561064e5760008585838181106104d8576104d7612b13565b5b90506020028101906104ea9190612b51565b6104f390612f72565b9050600081602001519050600081519050600081148061051857508260400151518114155b1561054f576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561060357600083828151811061056f5761056e612b13565b5b602002602001015190506105f26040518060a0016040528087600001518152602001838152602001876040015185815181106105ae576105ad612b13565b5b60200260200101518152602001876060015173ffffffffffffffffffffffffffffffffffffffff168152602001876080015167ffffffffffffffff168152506111b0565b506105fc8161144b565b9050610552565b50604051806040016040528084600001518152602001838152508585815181106106305761062f612b13565b5b60200260200101819052505050506106478161144b565b90506104bb565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634cb7e9e534836040518363ffffffff1660e01b81526004016106a99190613162565b6000604051808303818588803b1580156106c257600080fd5b505af11580156106d6573d6000803e3d6000fd5b505050505050505050565b6106e9611458565b80600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60006003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60007fea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af160001b905090565b6060600280546107bb906131b3565b80601f01602080910402602001604051908101604052809291908181526020018280546107e7906131b3565b80156108345780601f1061080957610100808354040283529160200191610834565b820191906000526020600020905b81548152906001019060200180831161081757829003601f168201915b5050505050905090565b600061085b8260a00160208101906108569190612a25565b6114df565b81806020019061086b91906131e4565b600001602081019061087d9190612a25565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108e1576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ea82611565565b9050919050565b6108fa336114df565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346926267826040518263ffffffff1660e01b815260040161095391906132c3565b600060405180830381600087803b15801561096d57600080fd5b505af1158015610981573d6000803e3d6000fd5b5050505050565b60606109b37f00000000000000000000000000000000000000000000000000000000000000006116b7565b6109dc7f00000000000000000000000000000000000000000000000000000000000000006116b7565b610a057f00000000000000000000000000000000000000000000000000000000000000006116b7565b604051602001610a1793929190613366565b604051602081830303815290604052905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b610a5b611458565b610a656000611785565b565b600060608060008060006060610a7b61184b565b610a83611886565b46306000801b600067ffffffffffffffff811115610aa457610aa3612ae4565b5b604051908082528060200260200182016040528015610ad25781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600083839050905060008167ffffffffffffffff811115610b6157610b60612ae4565b5b604051908082528060200260200182016040528015610b9a57816020015b610b87612269565b815260200190600190039081610b7f5790505b50905060005b82811015610d935736868683818110610bbc57610bbb612b13565b5b9050602002810190610bce91906133ad565b9050366000828060200190610be391906133d5565b9150915060008282905090506000811480610c0f5750838060400190610c099190613438565b90508114155b15610c46576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610d3b57610d2b6040518060a0016040528087600001358152602001868685818110610c7c57610c7b612b13565b5b9050602002810190610c8e91906131e4565b610c979061360c565b8152602001878060400190610cac9190613438565b85818110610cbd57610cbc612b13565b5b905060600201803603810190610cd3919061361f565b8152602001876060016020810190610ceb9190612a25565b73ffffffffffffffffffffffffffffffffffffffff168152602001876080016020810190610d19919061364c565b67ffffffffffffffff168152506118c1565b610d348161144b565b9050610c49565b50604051806040016040528085600001358152602001848490610d5e919061372c565b815250868681518110610d7457610d73612b13565b5b602002602001018190525050505050610d8c8161144b565b9050610ba0565b5060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166344adc90e34846040518363ffffffff1660e01b8152600401610df09190613a0d565b60006040518083038185885af1158015610e0e573d6000803e3d6000fd5b50505050506040513d6000823e3d601f19601f82011682018060405250810190610e389190613b07565b90506000805b84811015610f415736888883818110610e5a57610e59612b13565b5b9050602002810190610e6c91906133ad565b9050366000828060200190610e8191906133d5565b91509150600082829050905060005b81811015610f2c57846060016020810190610eab9190612a25565b600360008a8a81518110610ec257610ec1612b13565b5b6020026020010151815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866001019650610f258161144b565b9050610e90565b5050505050610f3a8161144b565b9050610e3e565b508194505050505092915050565b610f6881803603810190610f639190613bdd565b6111b0565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663469262673460405180604001604052808560000135815260200185602001803603810190610fce9190613c0b565b8152506040518363ffffffff1660e01b8152600401610fed9190613c67565b6000604051808303818588803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505050565b60066020528060005260406000206000915054906101000a900460ff1681565b60007f78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d60001b905090565b6000611077611a73565b905090565b6000611087336114df565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f17325e7836040518263ffffffff1660e01b81526004016110e09190613e96565b6020604051808303816000875af11580156110ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111239190613eb8565b9050919050565b611132611458565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111a45760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161119b9190612494565b60405180910390fd5b6111ad81611785565b50565b600067ffffffffffffffff16816080015167ffffffffffffffff16141580156111f757506111dc611b2a565b67ffffffffffffffff16816080015167ffffffffffffffff16105b1561122e576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816020015190506000600360008360000151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d9576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461133e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360400151905061135081611b32565b60006113c27f78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d60001b86606001518760000151876000015188602001518a608001516040516020016113a796959493929190613ef4565b60405160208183030381529060405280519060200120611c04565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166113f782846000015185602001518660400151611c1e565b73ffffffffffffffffffffffffffffffffffffffff1614611444576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000600182019050919050565b611460611c4e565b73ffffffffffffffffffffffffffffffffffffffff1661147e610b11565b73ffffffffffffffffffffffffffffffffffffffff16146114dd576114a1611c4e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016114d49190612494565b60405180910390fd5b565b600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611562576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60006115798261157490613ffd565b6118c1565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f17325e7346040518060400160405280876000013581526020018780602001906115dd91906131e4565b6115e69061360c565b8152506040518363ffffffff1660e01b8152600401611605919061404d565b60206040518083038185885af1158015611623573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906116489190613eb8565b90508260a001602081019061165d9190612a25565b6003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080915050919050565b6060600060016116c684611c56565b01905060008167ffffffffffffffff8111156116e5576116e4612ae4565b5b6040519080825280601f01601f1916602001820160405280156117175781602001600182028036833780820191505090505b509050600082602001820190505b60011561177a578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161176e5761176d61406f565b5b04945060008503611725575b819350505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b606061188160007f0000000000000000000000000000000000000000000000000000000000000000611da990919063ffffffff16565b905090565b60606118bc60017f0000000000000000000000000000000000000000000000000000000000000000611da990919063ffffffff16565b905090565b600067ffffffffffffffff16816080015167ffffffffffffffff161415801561190857506118ed611b2a565b67ffffffffffffffff16816080015167ffffffffffffffff16105b1561193f576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008160200151905060008260400151905061195a81611b32565b60006119eb7fea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af160001b8560600151866000015186600001518760200151886040015189606001518a60800151805190602001208b60a001518d608001516040516020016119d09a9998979695949392919061409e565b60405160208183030381529060405280519060200120611c04565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16611a2082846000015185602001518660400151611c1e565b73ffffffffffffffffffffffffffffffffffffffff1614611a6d576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611aef57507f000000000000000000000000000000000000000000000000000000000000000046145b15611b1c577f00000000000000000000000000000000000000000000000000000000000000009050611b27565b611b24611e59565b90505b90565b600042905090565b6000816000015182602001518360400151604051602001611b5593929190614191565b6040516020818303038152906040529050600481604051611b76919061420a565b908152602001604051809103902060009054906101000a900460ff1615611bc9576040517fcce9a82400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600482604051611bdb919061420a565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505050565b6000611c17611c11611a73565b83611eef565b9050919050565b600080600080611c3088888888611f30565b925092509250611c408282612024565b829350505050949350505050565b600033905090565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611cb4577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611caa57611ca961406f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611cf1576d04ee2d6d415b85acef81000000008381611ce757611ce661406f565b5b0492506020810190505b662386f26fc100008310611d2057662386f26fc100008381611d1657611d1561406f565b5b0492506010810190505b6305f5e1008310611d49576305f5e1008381611d3f57611d3e61406f565b5b0492506008810190505b6127108310611d6e576127108381611d6457611d6361406f565b5b0492506004810190505b60648310611d915760648381611d8757611d8661406f565b5b0492506002810190505b600a8310611da0576001810190505b80915050919050565b606060ff60001b8314611dc657611dbf83612188565b9050611e53565b818054611dd2906131b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611dfe906131b3565b8015611e4b5780601f10611e2057610100808354040283529160200191611e4b565b820191906000526020600020905b815481529060010190602001808311611e2e57829003601f168201915b505050505090505b92915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001611ed4959493929190614221565b60405160208183030381529060405280519060200120905090565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c1115611f7057600060038592509250925061201a565b600060018888888860405160008152602001604052604051611f959493929190614283565b6020604051602081039080840390855afa158015611fb7573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361200b57600060016000801b9350935093505061201a565b8060008060001b935093509350505b9450945094915050565b60006003811115612038576120376142c8565b5b82600381111561204b5761204a6142c8565b5b03156121845760016003811115612065576120646142c8565b5b826003811115612078576120776142c8565b5b036120af576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156120c3576120c26142c8565b5b8260038111156120d6576120d56142c8565b5b0361211b578060001c6040517ffce698f700000000000000000000000000000000000000000000000000000000815260040161211291906142f7565b60405180910390fd5b60038081111561212e5761212d6142c8565b5b826003811115612141576121406142c8565b5b0361218357806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161217a91906124be565b60405180910390fd5b5b5050565b60606000612195836121fc565b90506000602067ffffffffffffffff8111156121b4576121b3612ae4565b5b6040519080825280601f01601f1916602001820160405280156121e65781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612243576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b604051806040016040528060008019168152602001606081525090565b604051806040016040528060008019168152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f8401126122bf576122be61229a565b5b8235905067ffffffffffffffff8111156122dc576122db61229f565b5b6020830191508360208202830111156122f8576122f76122a4565b5b9250929050565b6000806020838503121561231657612315612290565b5b600083013567ffffffffffffffff81111561233457612333612295565b5b612340858286016122a9565b92509250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123778261234c565b9050919050565b6123878161236c565b811461239257600080fd5b50565b6000813590506123a48161237e565b92915050565b60008115159050919050565b6123bf816123aa565b81146123ca57600080fd5b50565b6000813590506123dc816123b6565b92915050565b600080604083850312156123f9576123f8612290565b5b600061240785828601612395565b9250506020612418858286016123cd565b9150509250929050565b6000819050919050565b61243581612422565b811461244057600080fd5b50565b6000813590506124528161242c565b92915050565b60006020828403121561246e5761246d612290565b5b600061247c84828501612443565b91505092915050565b61248e8161236c565b82525050565b60006020820190506124a96000830184612485565b92915050565b6124b881612422565b82525050565b60006020820190506124d360008301846124af565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125135780820151818401526020810190506124f8565b60008484015250505050565b6000601f19601f8301169050919050565b600061253b826124d9565b61254581856124e4565b93506125558185602086016124f5565b61255e8161251f565b840191505092915050565b600060208201905081810360008301526125838184612530565b905092915050565b600080fd5b600060e082840312156125a6576125a561258b565b5b81905092915050565b6000602082840312156125c5576125c4612290565b5b600082013567ffffffffffffffff8111156125e3576125e2612295565b5b6125ef84828501612590565b91505092915050565b60006060828403121561260e5761260d61258b565b5b81905092915050565b60006060828403121561262d5761262c612290565b5b600061263b848285016125f8565b91505092915050565b6000819050919050565b600061266961266461265f8461234c565b612644565b61234c565b9050919050565b600061267b8261264e565b9050919050565b600061268d82612670565b9050919050565b61269d81612682565b82525050565b60006020820190506126b86000830184612694565b92915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6126f3816126be565b82525050565b6000819050919050565b61270c816126f9565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612747816126f9565b82525050565b6000612759838361273e565b60208301905092915050565b6000602082019050919050565b600061277d82612712565b612787818561271d565b93506127928361272e565b8060005b838110156127c35781516127aa888261274d565b97506127b583612765565b925050600181019050612796565b5085935050505092915050565b600060e0820190506127e5600083018a6126ea565b81810360208301526127f78189612530565b9050818103604083015261280b8188612530565b905061281a6060830187612703565b6128276080830186612485565b61283460a08301856124af565b81810360c08301526128468184612772565b905098975050505050505050565b60008083601f84011261286a5761286961229a565b5b8235905067ffffffffffffffff8111156128875761288661229f565b5b6020830191508360208202830111156128a3576128a26122a4565b5b9250929050565b600080602083850312156128c1576128c0612290565b5b600083013567ffffffffffffffff8111156128df576128de612295565b5b6128eb85828601612854565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61292c81612422565b82525050565b600061293e8383612923565b60208301905092915050565b6000602082019050919050565b6000612962826128f7565b61296c8185612902565b935061297783612913565b8060005b838110156129a857815161298f8882612932565b975061299a8361294a565b92505060018101905061297b565b5085935050505092915050565b600060208201905081810360008301526129cf8184612957565b905092915050565b600061010082840312156129ee576129ed61258b565b5b81905092915050565b60006101008284031215612a0e57612a0d612290565b5b6000612a1c848285016129d7565b91505092915050565b600060208284031215612a3b57612a3a612290565b5b6000612a4984828501612395565b91505092915050565b612a5b816123aa565b82525050565b6000602082019050612a766000830184612a52565b92915050565b600060408284031215612a9257612a9161258b565b5b81905092915050565b600060208284031215612ab157612ab0612290565b5b600082013567ffffffffffffffff811115612acf57612ace612295565b5b612adb84828501612a7c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b60008235600160a003833603038112612b6d57612b6c612b42565b5b80830191505092915050565b600080fd5b612b878261251f565b810181811067ffffffffffffffff82111715612ba657612ba5612ae4565b5b80604052505050565b6000612bb9612286565b9050612bc58282612b7e565b919050565b600080fd5b600067ffffffffffffffff821115612bea57612be9612ae4565b5b602082029050602081019050919050565b612c04816126f9565b8114612c0f57600080fd5b50565b600081359050612c2181612bfb565b92915050565b600060408284031215612c3d57612c3c612b79565b5b612c476040612baf565b90506000612c5784828501612443565b6000830152506020612c6b84828501612c12565b60208301525092915050565b6000612c8a612c8584612bcf565b612baf565b90508083825260208201905060408402830185811115612cad57612cac6122a4565b5b835b81811015612cd65780612cc28882612c27565b845260208401935050604081019050612caf565b5050509392505050565b600082601f830112612cf557612cf461229a565b5b8135612d05848260208601612c77565b91505092915050565b600067ffffffffffffffff821115612d2957612d28612ae4565b5b602082029050602081019050919050565b600060ff82169050919050565b612d5081612d3a565b8114612d5b57600080fd5b50565b600081359050612d6d81612d47565b92915050565b600060608284031215612d8957612d88612b79565b5b612d936060612baf565b90506000612da384828501612d5e565b6000830152506020612db784828501612443565b6020830152506040612dcb84828501612443565b60408301525092915050565b6000612dea612de584612d0e565b612baf565b90508083825260208201905060608402830185811115612e0d57612e0c6122a4565b5b835b81811015612e365780612e228882612d73565b845260208401935050606081019050612e0f565b5050509392505050565b600082601f830112612e5557612e5461229a565b5b8135612e65848260208601612dd7565b91505092915050565b600067ffffffffffffffff82169050919050565b612e8b81612e6e565b8114612e9657600080fd5b50565b600081359050612ea881612e82565b92915050565b600060a08284031215612ec457612ec3612b79565b5b612ece60a0612baf565b90506000612ede84828501612443565b600083015250602082013567ffffffffffffffff811115612f0257612f01612bca565b5b612f0e84828501612ce0565b602083015250604082013567ffffffffffffffff811115612f3257612f31612bca565b5b612f3e84828501612e40565b6040830152506060612f5284828501612395565b6060830152506080612f6684828501612e99565b60808301525092915050565b6000612f7e3683612eae565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b604082016000820151612ff36000850182612923565b506020820151613006602085018261273e565b50505050565b60006130188383612fdd565b60408301905092915050565b6000602082019050919050565b600061303c82612fb1565b6130468185612fbc565b935061305183612fcd565b8060005b83811015613082578151613069888261300c565b975061307483613024565b925050600181019050613055565b5085935050505092915050565b60006040830160008301516130a76000860182612923565b50602083015184820360208601526130bf8282613031565b9150508091505092915050565b60006130d8838361308f565b905092915050565b6000602082019050919050565b60006130f882612f85565b6131028185612f90565b93508360208202850161311485612fa1565b8060005b85811015613150578484038952815161313185826130cc565b945061313c836130e0565b925060208a01995050600181019050613118565b50829750879550505050505092915050565b6000602082019050818103600083015261317c81846130ed565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131cb57607f821691505b6020821081036131de576131dd613184565b5b50919050565b60008235600160c003833603038112613200576131ff612b42565b5b80830191505092915050565b600061321b6020840184612443565b905092915050565b600082905092915050565b600061323d6020840184612c12565b905092915050565b60408201613256600083018361320c565b6132636000850182612923565b50613271602083018361322e565b61327e602085018261273e565b50505050565b60608201613295600083018361320c565b6132a26000850182612923565b506132b06020830183613223565b6132bd6020850182613245565b50505050565b60006060820190506132d86000830184613284565b92915050565b600081905092915050565b60006132f4826124d9565b6132fe81856132de565b935061330e8185602086016124f5565b80840191505092915050565b7f2e00000000000000000000000000000000000000000000000000000000000000600082015250565b60006133506001836132de565b915061335b8261331a565b600182019050919050565b600061337282866132e9565b915061337d82613343565b915061338982856132e9565b915061339482613343565b91506133a082846132e9565b9150819050949350505050565b60008235600160a0038336030381126133c9576133c8612b42565b5b80830191505092915050565b600080833560016020038436030381126133f2576133f1612b42565b5b80840192508235915067ffffffffffffffff82111561341457613413612b47565b5b6020830192506020820236038313156134305761342f612b4c565b5b509250929050565b6000808335600160200384360303811261345557613454612b42565b5b80840192508235915067ffffffffffffffff82111561347757613476612b47565b5b60208301925060608202360383131561349357613492612b4c565b5b509250929050565b600080fd5b600067ffffffffffffffff8211156134bb576134ba612ae4565b5b6134c48261251f565b9050602081019050919050565b82818337600083830152505050565b60006134f36134ee846134a0565b612baf565b90508281526020810184848401111561350f5761350e61349b565b5b61351a8482856134d1565b509392505050565b600082601f8301126135375761353661229a565b5b81356135478482602086016134e0565b91505092915050565b600060c0828403121561356657613565612b79565b5b61357060c0612baf565b9050600061358084828501612395565b600083015250602061359484828501612e99565b60208301525060406135a8848285016123cd565b60408301525060606135bc84828501612443565b606083015250608082013567ffffffffffffffff8111156135e0576135df612bca565b5b6135ec84828501613522565b60808301525060a061360084828501612c12565b60a08301525092915050565b60006136183683613550565b9050919050565b60006060828403121561363557613634612290565b5b600061364384828501612d73565b91505092915050565b60006020828403121561366257613661612290565b5b600061367084828501612e99565b91505092915050565b600067ffffffffffffffff82111561369457613693612ae4565b5b602082029050602081019050919050565b60006136b86136b384613679565b612baf565b905080838252602082019050602084028301858111156136db576136da6122a4565b5b835b8181101561372257803567ffffffffffffffff811115613700576136ff61229a565b5b80860161370d8982613550565b855260208501945050506020810190506136dd565b5050509392505050565b60006137393684846136a5565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137a28161236c565b82525050565b6137b181612e6e565b82525050565b6137c0816123aa565b82525050565b600081519050919050565b600082825260208201905092915050565b60006137ed826137c6565b6137f781856137d1565b93506138078185602086016124f5565b6138108161251f565b840191505092915050565b600060c0830160008301516138336000860182613799565b50602083015161384660208601826137a8565b50604083015161385960408601826137b7565b50606083015161386c6060860182612923565b506080830151848203608086015261388482826137e2565b91505060a083015161389960a086018261273e565b508091505092915050565b60006138b0838361381b565b905092915050565b6000602082019050919050565b60006138d08261376d565b6138da8185613778565b9350836020820285016138ec85613789565b8060005b85811015613928578484038952815161390985826138a4565b9450613914836138b8565b925060208a019950506001810190506138f0565b50829750879550505050505092915050565b60006040830160008301516139526000860182612923565b506020830151848203602086015261396a82826138c5565b9150508091505092915050565b6000613983838361393a565b905092915050565b6000602082019050919050565b60006139a382613741565b6139ad818561374c565b9350836020820285016139bf8561375d565b8060005b858110156139fb57848403895281516139dc8582613977565b94506139e78361398b565b925060208a019950506001810190506139c3565b50829750879550505050505092915050565b60006020820190508181036000830152613a278184613998565b905092915050565b600067ffffffffffffffff821115613a4a57613a49612ae4565b5b602082029050602081019050919050565b600081519050613a6a8161242c565b92915050565b6000613a83613a7e84613a2f565b612baf565b90508083825260208201905060208402830185811115613aa657613aa56122a4565b5b835b81811015613acf5780613abb8882613a5b565b845260208401935050602081019050613aa8565b5050509392505050565b600082601f830112613aee57613aed61229a565b5b8151613afe848260208601613a70565b91505092915050565b600060208284031215613b1d57613b1c612290565b5b600082015167ffffffffffffffff811115613b3b57613b3a612295565b5b613b4784828501613ad9565b91505092915050565b60006101008284031215613b6757613b66612b79565b5b613b7160a0612baf565b90506000613b8184828501612443565b6000830152506020613b9584828501612c27565b6020830152506060613ba984828501612d73565b60408301525060c0613bbd84828501612395565b60608301525060e0613bd184828501612e99565b60808301525092915050565b60006101008284031215613bf457613bf3612290565b5b6000613c0284828501613b50565b91505092915050565b600060408284031215613c2157613c20612290565b5b6000613c2f84828501612c27565b91505092915050565b606082016000820151613c4e6000850182612923565b506020820151613c616020850182612fdd565b50505050565b6000606082019050613c7c6000830184613c38565b92915050565b600080fd5b60008235600160c003833603038112613ca357613ca2613c82565b5b82810191505092915050565b6000613cbe6020840184612395565b905092915050565b6000613cd56020840184612e99565b905092915050565b6000613cec60208401846123cd565b905092915050565b600080fd5b600080fd5b60008083356001602003843603038112613d1b57613d1a613c82565b5b83810192508235915060208301925067ffffffffffffffff821115613d4357613d42613cf4565b5b600182023603831315613d5957613d58613cf9565b5b509250929050565b6000613d6d83856137d1565b9350613d7a8385846134d1565b613d838361251f565b840190509392505050565b600060c08301613da16000840184613caf565b613dae6000860182613799565b50613dbc6020840184613cc6565b613dc960208601826137a8565b50613dd76040840184613cdd565b613de460408601826137b7565b50613df2606084018461320c565b613dff6060860182612923565b50613e0d6080840184613cfe565b8583036080870152613e20838284613d61565b92505050613e3160a084018461322e565b613e3e60a086018261273e565b508091505092915050565b600060408301613e5c600084018461320c565b613e696000860182612923565b50613e776020840184613c87565b8482036020860152613e898282613d8e565b9150508091505092915050565b60006020820190508181036000830152613eb08184613e49565b905092915050565b600060208284031215613ece57613ecd612290565b5b6000613edc84828501613a5b565b91505092915050565b613eee81612e6e565b82525050565b600060c082019050613f0960008301896124af565b613f166020830188612485565b613f2360408301876124af565b613f3060608301866124af565b613f3d6080830185612703565b613f4a60a0830184613ee5565b979650505050505050565b600060e08284031215613f6b57613f6a612b79565b5b613f7560a0612baf565b90506000613f8584828501612443565b600083015250602082013567ffffffffffffffff811115613fa957613fa8612bca565b5b613fb584828501613550565b6020830152506040613fc984828501612d73565b60408301525060a0613fdd84828501612395565b60608301525060c0613ff184828501612e99565b60808301525092915050565b60006140093683613f55565b9050919050565b60006040830160008301516140286000860182612923565b5060208301518482036020860152614040828261381b565b9150508091505092915050565b600060208201905081810360008301526140678184614010565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610140820190506140b4600083018d6124af565b6140c1602083018c612485565b6140ce604083018b6124af565b6140db606083018a612485565b6140e86080830189613ee5565b6140f560a0830188612a52565b61410260c08301876124af565b61410f60e08301866124af565b61411d610100830185612703565b61412b610120830184613ee5565b9b9a5050505050505050505050565b60008160f81b9050919050565b60006141528261413a565b9050919050565b61416a61416582612d3a565b614147565b82525050565b6000819050919050565b61418b61418682612422565b614170565b82525050565b600061419d8286614159565b6001820191506141ad828561417a565b6020820191506141bd828461417a565b602082019150819050949350505050565b600081905092915050565b60006141e4826137c6565b6141ee81856141ce565b93506141fe8185602086016124f5565b80840191505092915050565b600061421682846141d9565b915081905092915050565b600060a08201905061423660008301886124af565b61424360208301876124af565b61425060408301866124af565b61425d6060830185612703565b61426a6080830184612485565b9695505050505050565b61427d81612d3a565b82525050565b600060808201905061429860008301876124af565b6142a56020830186614274565b6142b260408301856124af565b6142bf60608301846124af565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208201905061430c6000830184612703565b9291505056fea2646970667358221220a90eb035a3234a2cbc739f4b7d4ffb600ffd7e61f7f410ad13718e1f3ba7fffc64736f6c634300081a0033000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b0
Deployed Bytecode
0x6080604052600436106101145760003560e01c8063715018a6116100a0578063b6ebe53911610064578063b6ebe5391461035f578063b83010d31461039c578063ed24911d146103c7578063f17325e7146103f2578063f2fde38b1461042f57610114565b8063715018a6146102a057806384b0196e146102b75780638da5cb5b146102e85780639541152514610313578063a6d4dbc71461034357610114565b806317d7de7c116100e757806317d7de7c146101c65780633c042715146101f1578063469262671461022157806354fd4d501461024a57806365c40b9c1461027557610114565b80630eabf660146101195780630ee489481461013557806310d736d51461015e57806312b11a171461019b575b600080fd5b610133600480360381019061012e91906122ff565b610458565b005b34801561014157600080fd5b5061015c600480360381019061015791906123e2565b6106e1565b005b34801561016a57600080fd5b5061018560048036038101906101809190612458565b610744565b6040516101929190612494565b60405180910390f35b3480156101a757600080fd5b506101b0610781565b6040516101bd91906124be565b60405180910390f35b3480156101d257600080fd5b506101db6107ac565b6040516101e89190612569565b60405180910390f35b61020b600480360381019061020691906125af565b61083e565b60405161021891906124be565b60405180910390f35b34801561022d57600080fd5b5061024860048036038101906102439190612617565b6108f1565b005b34801561025657600080fd5b5061025f610988565b60405161026c9190612569565b60405180910390f35b34801561028157600080fd5b5061028a610a2b565b60405161029791906126a3565b60405180910390f35b3480156102ac57600080fd5b506102b5610a53565b005b3480156102c357600080fd5b506102cc610a67565b6040516102df97969594939291906127d0565b60405180910390f35b3480156102f457600080fd5b506102fd610b11565b60405161030a9190612494565b60405180910390f35b61032d600480360381019061032891906128aa565b610b3b565b60405161033a91906129b5565b60405180910390f35b61035d600480360381019061035891906129f7565b610f4f565b005b34801561036b57600080fd5b5061038660048036038101906103819190612a25565b611022565b6040516103939190612a61565b60405180910390f35b3480156103a857600080fd5b506103b1611042565b6040516103be91906124be565b60405180910390f35b3480156103d357600080fd5b506103dc61106d565b6040516103e991906124be565b60405180910390f35b3480156103fe57600080fd5b5061041960048036038101906104149190612a9b565b61107c565b60405161042691906124be565b60405180910390f35b34801561043b57600080fd5b5061045660048036038101906104519190612a25565b61112a565b005b600082829050905060008167ffffffffffffffff81111561047c5761047b612ae4565b5b6040519080825280602002602001820160405280156104b557816020015b6104a261224c565b81526020019060019003908161049a5790505b50905060005b8281101561064e5760008585838181106104d8576104d7612b13565b5b90506020028101906104ea9190612b51565b6104f390612f72565b9050600081602001519050600081519050600081148061051857508260400151518114155b1561054f576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561060357600083828151811061056f5761056e612b13565b5b602002602001015190506105f26040518060a0016040528087600001518152602001838152602001876040015185815181106105ae576105ad612b13565b5b60200260200101518152602001876060015173ffffffffffffffffffffffffffffffffffffffff168152602001876080015167ffffffffffffffff168152506111b0565b506105fc8161144b565b9050610552565b50604051806040016040528084600001518152602001838152508585815181106106305761062f612b13565b5b60200260200101819052505050506106478161144b565b90506104bb565b507f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff16634cb7e9e534836040518363ffffffff1660e01b81526004016106a99190613162565b6000604051808303818588803b1580156106c257600080fd5b505af11580156106d6573d6000803e3d6000fd5b505050505050505050565b6106e9611458565b80600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60006003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60007fea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af160001b905090565b6060600280546107bb906131b3565b80601f01602080910402602001604051908101604052809291908181526020018280546107e7906131b3565b80156108345780601f1061080957610100808354040283529160200191610834565b820191906000526020600020905b81548152906001019060200180831161081757829003601f168201915b5050505050905090565b600061085b8260a00160208101906108569190612a25565b6114df565b81806020019061086b91906131e4565b600001602081019061087d9190612a25565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108e1576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ea82611565565b9050919050565b6108fa336114df565b7f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff166346926267826040518263ffffffff1660e01b815260040161095391906132c3565b600060405180830381600087803b15801561096d57600080fd5b505af1158015610981573d6000803e3d6000fd5b5050505050565b60606109b37f00000000000000000000000000000000000000000000000000000000000000016116b7565b6109dc7f00000000000000000000000000000000000000000000000000000000000000036116b7565b610a057f00000000000000000000000000000000000000000000000000000000000000006116b7565b604051602001610a1793929190613366565b604051602081830303815290604052905090565b60007f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b0905090565b610a5b611458565b610a656000611785565b565b600060608060008060006060610a7b61184b565b610a83611886565b46306000801b600067ffffffffffffffff811115610aa457610aa3612ae4565b5b604051908082528060200260200182016040528015610ad25781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600083839050905060008167ffffffffffffffff811115610b6157610b60612ae4565b5b604051908082528060200260200182016040528015610b9a57816020015b610b87612269565b815260200190600190039081610b7f5790505b50905060005b82811015610d935736868683818110610bbc57610bbb612b13565b5b9050602002810190610bce91906133ad565b9050366000828060200190610be391906133d5565b9150915060008282905090506000811480610c0f5750838060400190610c099190613438565b90508114155b15610c46576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610d3b57610d2b6040518060a0016040528087600001358152602001868685818110610c7c57610c7b612b13565b5b9050602002810190610c8e91906131e4565b610c979061360c565b8152602001878060400190610cac9190613438565b85818110610cbd57610cbc612b13565b5b905060600201803603810190610cd3919061361f565b8152602001876060016020810190610ceb9190612a25565b73ffffffffffffffffffffffffffffffffffffffff168152602001876080016020810190610d19919061364c565b67ffffffffffffffff168152506118c1565b610d348161144b565b9050610c49565b50604051806040016040528085600001358152602001848490610d5e919061372c565b815250868681518110610d7457610d73612b13565b5b602002602001018190525050505050610d8c8161144b565b9050610ba0565b5060007f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff166344adc90e34846040518363ffffffff1660e01b8152600401610df09190613a0d565b60006040518083038185885af1158015610e0e573d6000803e3d6000fd5b50505050506040513d6000823e3d601f19601f82011682018060405250810190610e389190613b07565b90506000805b84811015610f415736888883818110610e5a57610e59612b13565b5b9050602002810190610e6c91906133ad565b9050366000828060200190610e8191906133d5565b91509150600082829050905060005b81811015610f2c57846060016020810190610eab9190612a25565b600360008a8a81518110610ec257610ec1612b13565b5b6020026020010151815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866001019650610f258161144b565b9050610e90565b5050505050610f3a8161144b565b9050610e3e565b508194505050505092915050565b610f6881803603810190610f639190613bdd565b6111b0565b7f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff1663469262673460405180604001604052808560000135815260200185602001803603810190610fce9190613c0b565b8152506040518363ffffffff1660e01b8152600401610fed9190613c67565b6000604051808303818588803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505050565b60066020528060005260406000206000915054906101000a900460ff1681565b60007f78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d60001b905090565b6000611077611a73565b905090565b6000611087336114df565b7f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff1663f17325e7836040518263ffffffff1660e01b81526004016110e09190613e96565b6020604051808303816000875af11580156110ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111239190613eb8565b9050919050565b611132611458565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111a45760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161119b9190612494565b60405180910390fd5b6111ad81611785565b50565b600067ffffffffffffffff16816080015167ffffffffffffffff16141580156111f757506111dc611b2a565b67ffffffffffffffff16816080015167ffffffffffffffff16105b1561122e576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816020015190506000600360008360000151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d9576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461133e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360400151905061135081611b32565b60006113c27f78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d60001b86606001518760000151876000015188602001518a608001516040516020016113a796959493929190613ef4565b60405160208183030381529060405280519060200120611c04565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166113f782846000015185602001518660400151611c1e565b73ffffffffffffffffffffffffffffffffffffffff1614611444576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000600182019050919050565b611460611c4e565b73ffffffffffffffffffffffffffffffffffffffff1661147e610b11565b73ffffffffffffffffffffffffffffffffffffffff16146114dd576114a1611c4e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016114d49190612494565b60405180910390fd5b565b600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611562576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60006115798261157490613ffd565b6118c1565b60007f000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b073ffffffffffffffffffffffffffffffffffffffff1663f17325e7346040518060400160405280876000013581526020018780602001906115dd91906131e4565b6115e69061360c565b8152506040518363ffffffff1660e01b8152600401611605919061404d565b60206040518083038185885af1158015611623573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906116489190613eb8565b90508260a001602081019061165d9190612a25565b6003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080915050919050565b6060600060016116c684611c56565b01905060008167ffffffffffffffff8111156116e5576116e4612ae4565b5b6040519080825280601f01601f1916602001820160405280156117175781602001600182028036833780820191505090505b509050600082602001820190505b60011561177a578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161176e5761176d61406f565b5b04945060008503611725575b819350505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b606061188160007f417474657374657250726f78790000000000000000000000000000000000000d611da990919063ffffffff16565b905090565b60606118bc60017f312e332e30000000000000000000000000000000000000000000000000000005611da990919063ffffffff16565b905090565b600067ffffffffffffffff16816080015167ffffffffffffffff161415801561190857506118ed611b2a565b67ffffffffffffffff16816080015167ffffffffffffffff16105b1561193f576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008160200151905060008260400151905061195a81611b32565b60006119eb7fea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af160001b8560600151866000015186600001518760200151886040015189606001518a60800151805190602001208b60a001518d608001516040516020016119d09a9998979695949392919061409e565b60405160208183030381529060405280519060200120611c04565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16611a2082846000015185602001518660400151611c1e565b73ffffffffffffffffffffffffffffffffffffffff1614611a6d576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60007f0000000000000000000000003d52d95d58fcb53814ea37d580601d2af2b4cc9873ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611aef57507f000000000000000000000000000000000000000000000000000000000008275046145b15611b1c577fd1ccfc18a1d8ca5758245b1fcb0da63a6ecd06c9ac95931e7eeb3dfb607aaca89050611b27565b611b24611e59565b90505b90565b600042905090565b6000816000015182602001518360400151604051602001611b5593929190614191565b6040516020818303038152906040529050600481604051611b76919061420a565b908152602001604051809103902060009054906101000a900460ff1615611bc9576040517fcce9a82400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600482604051611bdb919061420a565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505050565b6000611c17611c11611a73565b83611eef565b9050919050565b600080600080611c3088888888611f30565b925092509250611c408282612024565b829350505050949350505050565b600033905090565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611cb4577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611caa57611ca961406f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611cf1576d04ee2d6d415b85acef81000000008381611ce757611ce661406f565b5b0492506020810190505b662386f26fc100008310611d2057662386f26fc100008381611d1657611d1561406f565b5b0492506010810190505b6305f5e1008310611d49576305f5e1008381611d3f57611d3e61406f565b5b0492506008810190505b6127108310611d6e576127108381611d6457611d6361406f565b5b0492506004810190505b60648310611d915760648381611d8757611d8661406f565b5b0492506002810190505b600a8310611da0576001810190505b80915050919050565b606060ff60001b8314611dc657611dbf83612188565b9050611e53565b818054611dd2906131b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611dfe906131b3565b8015611e4b5780601f10611e2057610100808354040283529160200191611e4b565b820191906000526020600020905b815481529060010190602001808311611e2e57829003601f168201915b505050505090505b92915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f97bb23b7039fbf807a19c2f6dd506213960f67136e67b18f347fb9a2b29314687f6a08c3e203132c561752255a4d52ffae85bb9c5d33cb3291520dea1b843563894630604051602001611ed4959493929190614221565b60405160208183030381529060405280519060200120905090565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c1115611f7057600060038592509250925061201a565b600060018888888860405160008152602001604052604051611f959493929190614283565b6020604051602081039080840390855afa158015611fb7573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361200b57600060016000801b9350935093505061201a565b8060008060001b935093509350505b9450945094915050565b60006003811115612038576120376142c8565b5b82600381111561204b5761204a6142c8565b5b03156121845760016003811115612065576120646142c8565b5b826003811115612078576120776142c8565b5b036120af576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156120c3576120c26142c8565b5b8260038111156120d6576120d56142c8565b5b0361211b578060001c6040517ffce698f700000000000000000000000000000000000000000000000000000000815260040161211291906142f7565b60405180910390fd5b60038081111561212e5761212d6142c8565b5b826003811115612141576121406142c8565b5b0361218357806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161217a91906124be565b60405180910390fd5b5b5050565b60606000612195836121fc565b90506000602067ffffffffffffffff8111156121b4576121b3612ae4565b5b6040519080825280601f01601f1916602001820160405280156121e65781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612243576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b604051806040016040528060008019168152602001606081525090565b604051806040016040528060008019168152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f8401126122bf576122be61229a565b5b8235905067ffffffffffffffff8111156122dc576122db61229f565b5b6020830191508360208202830111156122f8576122f76122a4565b5b9250929050565b6000806020838503121561231657612315612290565b5b600083013567ffffffffffffffff81111561233457612333612295565b5b612340858286016122a9565b92509250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123778261234c565b9050919050565b6123878161236c565b811461239257600080fd5b50565b6000813590506123a48161237e565b92915050565b60008115159050919050565b6123bf816123aa565b81146123ca57600080fd5b50565b6000813590506123dc816123b6565b92915050565b600080604083850312156123f9576123f8612290565b5b600061240785828601612395565b9250506020612418858286016123cd565b9150509250929050565b6000819050919050565b61243581612422565b811461244057600080fd5b50565b6000813590506124528161242c565b92915050565b60006020828403121561246e5761246d612290565b5b600061247c84828501612443565b91505092915050565b61248e8161236c565b82525050565b60006020820190506124a96000830184612485565b92915050565b6124b881612422565b82525050565b60006020820190506124d360008301846124af565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125135780820151818401526020810190506124f8565b60008484015250505050565b6000601f19601f8301169050919050565b600061253b826124d9565b61254581856124e4565b93506125558185602086016124f5565b61255e8161251f565b840191505092915050565b600060208201905081810360008301526125838184612530565b905092915050565b600080fd5b600060e082840312156125a6576125a561258b565b5b81905092915050565b6000602082840312156125c5576125c4612290565b5b600082013567ffffffffffffffff8111156125e3576125e2612295565b5b6125ef84828501612590565b91505092915050565b60006060828403121561260e5761260d61258b565b5b81905092915050565b60006060828403121561262d5761262c612290565b5b600061263b848285016125f8565b91505092915050565b6000819050919050565b600061266961266461265f8461234c565b612644565b61234c565b9050919050565b600061267b8261264e565b9050919050565b600061268d82612670565b9050919050565b61269d81612682565b82525050565b60006020820190506126b86000830184612694565b92915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6126f3816126be565b82525050565b6000819050919050565b61270c816126f9565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612747816126f9565b82525050565b6000612759838361273e565b60208301905092915050565b6000602082019050919050565b600061277d82612712565b612787818561271d565b93506127928361272e565b8060005b838110156127c35781516127aa888261274d565b97506127b583612765565b925050600181019050612796565b5085935050505092915050565b600060e0820190506127e5600083018a6126ea565b81810360208301526127f78189612530565b9050818103604083015261280b8188612530565b905061281a6060830187612703565b6128276080830186612485565b61283460a08301856124af565b81810360c08301526128468184612772565b905098975050505050505050565b60008083601f84011261286a5761286961229a565b5b8235905067ffffffffffffffff8111156128875761288661229f565b5b6020830191508360208202830111156128a3576128a26122a4565b5b9250929050565b600080602083850312156128c1576128c0612290565b5b600083013567ffffffffffffffff8111156128df576128de612295565b5b6128eb85828601612854565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61292c81612422565b82525050565b600061293e8383612923565b60208301905092915050565b6000602082019050919050565b6000612962826128f7565b61296c8185612902565b935061297783612913565b8060005b838110156129a857815161298f8882612932565b975061299a8361294a565b92505060018101905061297b565b5085935050505092915050565b600060208201905081810360008301526129cf8184612957565b905092915050565b600061010082840312156129ee576129ed61258b565b5b81905092915050565b60006101008284031215612a0e57612a0d612290565b5b6000612a1c848285016129d7565b91505092915050565b600060208284031215612a3b57612a3a612290565b5b6000612a4984828501612395565b91505092915050565b612a5b816123aa565b82525050565b6000602082019050612a766000830184612a52565b92915050565b600060408284031215612a9257612a9161258b565b5b81905092915050565b600060208284031215612ab157612ab0612290565b5b600082013567ffffffffffffffff811115612acf57612ace612295565b5b612adb84828501612a7c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b60008235600160a003833603038112612b6d57612b6c612b42565b5b80830191505092915050565b600080fd5b612b878261251f565b810181811067ffffffffffffffff82111715612ba657612ba5612ae4565b5b80604052505050565b6000612bb9612286565b9050612bc58282612b7e565b919050565b600080fd5b600067ffffffffffffffff821115612bea57612be9612ae4565b5b602082029050602081019050919050565b612c04816126f9565b8114612c0f57600080fd5b50565b600081359050612c2181612bfb565b92915050565b600060408284031215612c3d57612c3c612b79565b5b612c476040612baf565b90506000612c5784828501612443565b6000830152506020612c6b84828501612c12565b60208301525092915050565b6000612c8a612c8584612bcf565b612baf565b90508083825260208201905060408402830185811115612cad57612cac6122a4565b5b835b81811015612cd65780612cc28882612c27565b845260208401935050604081019050612caf565b5050509392505050565b600082601f830112612cf557612cf461229a565b5b8135612d05848260208601612c77565b91505092915050565b600067ffffffffffffffff821115612d2957612d28612ae4565b5b602082029050602081019050919050565b600060ff82169050919050565b612d5081612d3a565b8114612d5b57600080fd5b50565b600081359050612d6d81612d47565b92915050565b600060608284031215612d8957612d88612b79565b5b612d936060612baf565b90506000612da384828501612d5e565b6000830152506020612db784828501612443565b6020830152506040612dcb84828501612443565b60408301525092915050565b6000612dea612de584612d0e565b612baf565b90508083825260208201905060608402830185811115612e0d57612e0c6122a4565b5b835b81811015612e365780612e228882612d73565b845260208401935050606081019050612e0f565b5050509392505050565b600082601f830112612e5557612e5461229a565b5b8135612e65848260208601612dd7565b91505092915050565b600067ffffffffffffffff82169050919050565b612e8b81612e6e565b8114612e9657600080fd5b50565b600081359050612ea881612e82565b92915050565b600060a08284031215612ec457612ec3612b79565b5b612ece60a0612baf565b90506000612ede84828501612443565b600083015250602082013567ffffffffffffffff811115612f0257612f01612bca565b5b612f0e84828501612ce0565b602083015250604082013567ffffffffffffffff811115612f3257612f31612bca565b5b612f3e84828501612e40565b6040830152506060612f5284828501612395565b6060830152506080612f6684828501612e99565b60808301525092915050565b6000612f7e3683612eae565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b604082016000820151612ff36000850182612923565b506020820151613006602085018261273e565b50505050565b60006130188383612fdd565b60408301905092915050565b6000602082019050919050565b600061303c82612fb1565b6130468185612fbc565b935061305183612fcd565b8060005b83811015613082578151613069888261300c565b975061307483613024565b925050600181019050613055565b5085935050505092915050565b60006040830160008301516130a76000860182612923565b50602083015184820360208601526130bf8282613031565b9150508091505092915050565b60006130d8838361308f565b905092915050565b6000602082019050919050565b60006130f882612f85565b6131028185612f90565b93508360208202850161311485612fa1565b8060005b85811015613150578484038952815161313185826130cc565b945061313c836130e0565b925060208a01995050600181019050613118565b50829750879550505050505092915050565b6000602082019050818103600083015261317c81846130ed565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131cb57607f821691505b6020821081036131de576131dd613184565b5b50919050565b60008235600160c003833603038112613200576131ff612b42565b5b80830191505092915050565b600061321b6020840184612443565b905092915050565b600082905092915050565b600061323d6020840184612c12565b905092915050565b60408201613256600083018361320c565b6132636000850182612923565b50613271602083018361322e565b61327e602085018261273e565b50505050565b60608201613295600083018361320c565b6132a26000850182612923565b506132b06020830183613223565b6132bd6020850182613245565b50505050565b60006060820190506132d86000830184613284565b92915050565b600081905092915050565b60006132f4826124d9565b6132fe81856132de565b935061330e8185602086016124f5565b80840191505092915050565b7f2e00000000000000000000000000000000000000000000000000000000000000600082015250565b60006133506001836132de565b915061335b8261331a565b600182019050919050565b600061337282866132e9565b915061337d82613343565b915061338982856132e9565b915061339482613343565b91506133a082846132e9565b9150819050949350505050565b60008235600160a0038336030381126133c9576133c8612b42565b5b80830191505092915050565b600080833560016020038436030381126133f2576133f1612b42565b5b80840192508235915067ffffffffffffffff82111561341457613413612b47565b5b6020830192506020820236038313156134305761342f612b4c565b5b509250929050565b6000808335600160200384360303811261345557613454612b42565b5b80840192508235915067ffffffffffffffff82111561347757613476612b47565b5b60208301925060608202360383131561349357613492612b4c565b5b509250929050565b600080fd5b600067ffffffffffffffff8211156134bb576134ba612ae4565b5b6134c48261251f565b9050602081019050919050565b82818337600083830152505050565b60006134f36134ee846134a0565b612baf565b90508281526020810184848401111561350f5761350e61349b565b5b61351a8482856134d1565b509392505050565b600082601f8301126135375761353661229a565b5b81356135478482602086016134e0565b91505092915050565b600060c0828403121561356657613565612b79565b5b61357060c0612baf565b9050600061358084828501612395565b600083015250602061359484828501612e99565b60208301525060406135a8848285016123cd565b60408301525060606135bc84828501612443565b606083015250608082013567ffffffffffffffff8111156135e0576135df612bca565b5b6135ec84828501613522565b60808301525060a061360084828501612c12565b60a08301525092915050565b60006136183683613550565b9050919050565b60006060828403121561363557613634612290565b5b600061364384828501612d73565b91505092915050565b60006020828403121561366257613661612290565b5b600061367084828501612e99565b91505092915050565b600067ffffffffffffffff82111561369457613693612ae4565b5b602082029050602081019050919050565b60006136b86136b384613679565b612baf565b905080838252602082019050602084028301858111156136db576136da6122a4565b5b835b8181101561372257803567ffffffffffffffff811115613700576136ff61229a565b5b80860161370d8982613550565b855260208501945050506020810190506136dd565b5050509392505050565b60006137393684846136a5565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137a28161236c565b82525050565b6137b181612e6e565b82525050565b6137c0816123aa565b82525050565b600081519050919050565b600082825260208201905092915050565b60006137ed826137c6565b6137f781856137d1565b93506138078185602086016124f5565b6138108161251f565b840191505092915050565b600060c0830160008301516138336000860182613799565b50602083015161384660208601826137a8565b50604083015161385960408601826137b7565b50606083015161386c6060860182612923565b506080830151848203608086015261388482826137e2565b91505060a083015161389960a086018261273e565b508091505092915050565b60006138b0838361381b565b905092915050565b6000602082019050919050565b60006138d08261376d565b6138da8185613778565b9350836020820285016138ec85613789565b8060005b85811015613928578484038952815161390985826138a4565b9450613914836138b8565b925060208a019950506001810190506138f0565b50829750879550505050505092915050565b60006040830160008301516139526000860182612923565b506020830151848203602086015261396a82826138c5565b9150508091505092915050565b6000613983838361393a565b905092915050565b6000602082019050919050565b60006139a382613741565b6139ad818561374c565b9350836020820285016139bf8561375d565b8060005b858110156139fb57848403895281516139dc8582613977565b94506139e78361398b565b925060208a019950506001810190506139c3565b50829750879550505050505092915050565b60006020820190508181036000830152613a278184613998565b905092915050565b600067ffffffffffffffff821115613a4a57613a49612ae4565b5b602082029050602081019050919050565b600081519050613a6a8161242c565b92915050565b6000613a83613a7e84613a2f565b612baf565b90508083825260208201905060208402830185811115613aa657613aa56122a4565b5b835b81811015613acf5780613abb8882613a5b565b845260208401935050602081019050613aa8565b5050509392505050565b600082601f830112613aee57613aed61229a565b5b8151613afe848260208601613a70565b91505092915050565b600060208284031215613b1d57613b1c612290565b5b600082015167ffffffffffffffff811115613b3b57613b3a612295565b5b613b4784828501613ad9565b91505092915050565b60006101008284031215613b6757613b66612b79565b5b613b7160a0612baf565b90506000613b8184828501612443565b6000830152506020613b9584828501612c27565b6020830152506060613ba984828501612d73565b60408301525060c0613bbd84828501612395565b60608301525060e0613bd184828501612e99565b60808301525092915050565b60006101008284031215613bf457613bf3612290565b5b6000613c0284828501613b50565b91505092915050565b600060408284031215613c2157613c20612290565b5b6000613c2f84828501612c27565b91505092915050565b606082016000820151613c4e6000850182612923565b506020820151613c616020850182612fdd565b50505050565b6000606082019050613c7c6000830184613c38565b92915050565b600080fd5b60008235600160c003833603038112613ca357613ca2613c82565b5b82810191505092915050565b6000613cbe6020840184612395565b905092915050565b6000613cd56020840184612e99565b905092915050565b6000613cec60208401846123cd565b905092915050565b600080fd5b600080fd5b60008083356001602003843603038112613d1b57613d1a613c82565b5b83810192508235915060208301925067ffffffffffffffff821115613d4357613d42613cf4565b5b600182023603831315613d5957613d58613cf9565b5b509250929050565b6000613d6d83856137d1565b9350613d7a8385846134d1565b613d838361251f565b840190509392505050565b600060c08301613da16000840184613caf565b613dae6000860182613799565b50613dbc6020840184613cc6565b613dc960208601826137a8565b50613dd76040840184613cdd565b613de460408601826137b7565b50613df2606084018461320c565b613dff6060860182612923565b50613e0d6080840184613cfe565b8583036080870152613e20838284613d61565b92505050613e3160a084018461322e565b613e3e60a086018261273e565b508091505092915050565b600060408301613e5c600084018461320c565b613e696000860182612923565b50613e776020840184613c87565b8482036020860152613e898282613d8e565b9150508091505092915050565b60006020820190508181036000830152613eb08184613e49565b905092915050565b600060208284031215613ece57613ecd612290565b5b6000613edc84828501613a5b565b91505092915050565b613eee81612e6e565b82525050565b600060c082019050613f0960008301896124af565b613f166020830188612485565b613f2360408301876124af565b613f3060608301866124af565b613f3d6080830185612703565b613f4a60a0830184613ee5565b979650505050505050565b600060e08284031215613f6b57613f6a612b79565b5b613f7560a0612baf565b90506000613f8584828501612443565b600083015250602082013567ffffffffffffffff811115613fa957613fa8612bca565b5b613fb584828501613550565b6020830152506040613fc984828501612d73565b60408301525060a0613fdd84828501612395565b60608301525060c0613ff184828501612e99565b60808301525092915050565b60006140093683613f55565b9050919050565b60006040830160008301516140286000860182612923565b5060208301518482036020860152614040828261381b565b9150508091505092915050565b600060208201905081810360008301526140678184614010565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000610140820190506140b4600083018d6124af565b6140c1602083018c612485565b6140ce604083018b6124af565b6140db606083018a612485565b6140e86080830189613ee5565b6140f560a0830188612a52565b61410260c08301876124af565b61410f60e08301866124af565b61411d610100830185612703565b61412b610120830184613ee5565b9b9a5050505050505050505050565b60008160f81b9050919050565b60006141528261413a565b9050919050565b61416a61416582612d3a565b614147565b82525050565b6000819050919050565b61418b61418682612422565b614170565b82525050565b600061419d8286614159565b6001820191506141ad828561417a565b6020820191506141bd828461417a565b602082019150819050949350505050565b600081905092915050565b60006141e4826137c6565b6141ee81856141ce565b93506141fe8185602086016124f5565b80840191505092915050565b600061421682846141d9565b915081905092915050565b600060a08201905061423660008301886124af565b61424360208301876124af565b61425060408301866124af565b61425d6060830185612703565b61426a6080830184612485565b9695505050505050565b61427d81612d3a565b82525050565b600060808201905061429860008301876124af565b6142a56020830186614274565b6142b260408301856124af565b6142bf60608301846124af565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208201905061430c6000830184612703565b9291505056fea2646970667358221220a90eb035a3234a2cbc739f4b7d4ffb600ffd7e61f7f410ad13718e1f3ba7fffc64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b0
-----Decoded View---------------
Arg [0] : eas (address): 0xC47300428b6AD2c7D03BB76D05A176058b47E6B0
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c47300428b6ad2c7d03bb76d05a176058b47e6b0
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.