Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SecureSgxVerifier
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- cancun
- Verified at
- 2026-06-24T09:36:30.319950Z
Constructor Arguments
0x0000000000000000000000000000000000000000000000000000000000028c590000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b8000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e0000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b8
Arg [0] (uint64) : 167001
Arg [1] (address) : 0x4779d18931b35540f84b0cd0e9633855b84df7b8
Arg [2] (address) : 0x044c2e53e9edddd1353a9d923fa39c1fa821e88e
Arg [3] (address) : 0x4779d18931b35540f84b0cd0e9633855b84df7b8
contracts/layer1/verifiers/SecureSgxVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { SgxVerifier } from "./SgxVerifier.sol";
import { TCBInfoStruct } from "src/layer1/automata-attestation/lib/TCBInfoStruct.sol";
/// @title SecureSgxVerifier
/// @notice SGX verifier with the strict TCB-status acceptance policy intended for mainnet/production.
/// @custom:security-contact security@taiko.xyz
contract SecureSgxVerifier is SgxVerifier {
constructor(
uint64 _taikoChainId,
address _owner,
address _automataDcapAttestation,
address _registrar
)
SgxVerifier(_taikoChainId, _owner, _automataDcapAttestation, _registrar)
{ }
/// @inheritdoc SgxVerifier
/// @dev Strict policy: accept the TCB statuses whose platform microcode is up to date — `OK`,
/// `TCB_SW_HARDENING_NEEDED` and `TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED` (their mitigations
/// live in configuration / enclave software pinned by the MRENCLAVE allowlist, not in microcode).
/// The out-of-date statuses (`TCB_OUT_OF_DATE`, `TCB_OUT_OF_DATE_CONFIGURATION_NEEDED`) are
/// rejected, where the platform may be missing the microcode that patches SGX key-extraction
/// vulnerabilities (so the in-enclave signing key could be extractable); `TCB_CONFIGURATION_NEEDED`,
/// `TCB_REVOKED` and `TCB_UNRECOGNIZED` are rejected too. The policy is expressed against the
/// attestation's `TCBInfoStruct.TCBStatus` enum so an enum reorder is caught at compile time.
function isTcbStatusAccepted(uint8 _status) public pure override returns (bool) {
return _status == uint8(TCBInfoStruct.TCBStatus.OK)
|| _status == uint8(TCBInfoStruct.TCBStatus.TCB_SW_HARDENING_NEEDED)
|| _status == uint8(TCBInfoStruct.TCBStatus.TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED);
}
}
node_modules/@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
contracts/layer1/automata-attestation/interfaces/IAttestation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "../lib/QuoteV3Auth/V3Struct.sol";
/// @title IAttestation
/// @custom:security-contact security@taiko.xyz
interface IAttestation {
function verifyAttestation(bytes calldata data) external returns (bool);
function verifyParsedQuote(V3Struct.ParsedV3QuoteStruct calldata v3quote)
external
returns (bool success, bytes memory retData);
}
contracts/layer1/automata-attestation/lib/QuoteV3Auth/V3Struct.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title V3Struct
/// @custom:security-contact security@taiko.xyz
library V3Struct {
struct Header {
bytes2 version;
bytes2 attestationKeyType;
bytes4 teeType;
bytes2 qeSvn;
bytes2 pceSvn;
bytes16 qeVendorId;
bytes20 userData;
}
struct EnclaveReport {
bytes16 cpuSvn;
bytes4 miscSelect;
bytes28 reserved1;
bytes16 attributes;
bytes32 mrEnclave;
bytes32 reserved2;
bytes32 mrSigner;
bytes reserved3; // 96 bytes
uint16 isvProdId;
uint16 isvSvn;
bytes reserved4; // 60 bytes
bytes reportData; // 64 bytes - For QEReports, this contains the hash of the concatenation
// of attestation key and QEAuthData
}
struct QEAuthData {
uint16 parsedDataSize;
bytes data;
}
struct CertificationData {
uint16 certType;
// TODO(Yue): In encoded path, we need to calculate the size of certDataArray
// certDataSize = len(join((BEGIN_CERT, certArray[i], END_CERT) for i in 0..3))
// But for plain bytes path, we don't need that.
uint32 certDataSize;
bytes[3] decodedCertDataArray; // base64 decoded cert bytes array
}
struct ECDSAQuoteV3AuthData {
bytes ecdsa256BitSignature; // 64 bytes
bytes ecdsaAttestationKey; // 64 bytes
EnclaveReport pckSignedQeReport; // 384 bytes
bytes qeReportSignature; // 64 bytes
QEAuthData qeAuthData;
CertificationData certification;
}
struct ParsedV3QuoteStruct {
Header header;
EnclaveReport localEnclaveReport;
ECDSAQuoteV3AuthData v3AuthData;
}
}
contracts/layer1/automata-attestation/lib/TCBInfoStruct.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title TCBInfoStruct
/// @custom:security-contact security@taiko.xyz
library TCBInfoStruct {
struct TCBInfo {
string pceid;
string fmspc;
TCBLevelObj[] tcbLevels;
}
struct TCBLevelObj {
uint256 pcesvn;
uint8[] sgxTcbCompSvnArr;
TCBStatus status;
}
enum TCBStatus {
OK,
TCB_SW_HARDENING_NEEDED,
TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED,
TCB_CONFIGURATION_NEEDED,
TCB_OUT_OF_DATE,
TCB_OUT_OF_DATE_CONFIGURATION_NEEDED,
TCB_REVOKED,
TCB_UNRECOGNIZED
}
}
contracts/layer1/verifiers/IProofVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProofVerifier
/// @notice Interface for verifying validity proofs for state transitions
/// @custom:security-contact security@taiko.xyz
interface IProofVerifier {
/// @notice Verifies a validity proof for a state transition
/// @dev This function must revert if the proof is invalid
/// @param _proposalAge The age in seconds of the proposal being proven. Only set for
/// single-proposal proofs (calculated as block.timestamp - proposal.timestamp).
/// For multi-proposal batches, this is always 0, meaning "not applicable".
/// Verifiers should interpret _proposalAge == 0 as "not applicable" rather than
/// "instant proof". This parameter enables age-based verification logic, such as
/// detecting and handling prover-killer proposals differently.
/// @param _commitmentHash Hash of the last proposal hash and commitment data
/// @param _proof The proof data
function verifyProof(
uint256 _proposalAge,
bytes32 _commitmentHash,
bytes calldata _proof
)
external
view;
}
contracts/layer1/verifiers/LibPublicInput.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { EfficientHashLib } from "solady/src/utils/EfficientHashLib.sol";
/// @title LibPublicInput
/// @notice A library for handling hashing the so-called public input hash, used by sgx and zk
/// proofs.
/// @custom:security-contact security@taiko.xyz
library LibPublicInput {
/// @notice Hashes the public input for the proof verification.
/// @param _aggregatedProvingHash The aggregated proving hash from the inbox.
/// @param _verifierContract The contract address which as current verifier.
/// @param _proofSigner The address of the instance that signed this proof. For SGX it is the
/// signer address, for ZK this variable is not used and must have value address(0).
/// @param _chainId The chain id.
/// @return The public input hash.
function hashPublicInputs(
bytes32 _aggregatedProvingHash,
address _verifierContract,
address _proofSigner,
uint64 _chainId
)
internal
pure
returns (bytes32)
{
require(_aggregatedProvingHash != bytes32(0), InvalidAggregatedProvingHash());
return EfficientHashLib.hash(
bytes32("VERIFY_PROOF"),
bytes32(uint256(_chainId)),
bytes32(uint256(uint160(_verifierContract))),
_aggregatedProvingHash,
bytes32(uint256(uint160(_proofSigner)))
);
}
/// @dev Hashes the public input for the ZK aggregation proof verification,
/// which contains the sub image id to be aggregated for security.
/// @param _blockProvingProgram The proving program identifier.
/// @param _aggregatedProvingHash The aggregated proving hash from the inbox.
/// @return The ZK aggregation public input hash.
function hashZKAggregationPublicInputs(
bytes32 _blockProvingProgram,
bytes32 _aggregatedProvingHash
)
internal
pure
returns (bytes32)
{
return EfficientHashLib.hash(_blockProvingProgram, _aggregatedProvingHash);
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error InvalidAggregatedProvingHash();
}
contracts/layer1/verifiers/SgxVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IProofVerifier } from "./IProofVerifier.sol";
import { LibPublicInput } from "./LibPublicInput.sol";
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { IAttestation } from "src/layer1/automata-attestation/interfaces/IAttestation.sol";
import { V3Struct } from "src/layer1/automata-attestation/lib/QuoteV3Auth/V3Struct.sol";
/// @title SgxVerifier
/// @notice Abstract base that verifies SGX signature proofs onchain using attested SGX instances.
/// Each instance is registered via remote attestation and can verify proofs until expiry. The
/// TCB-status acceptance policy is left abstract so that per-network subclasses define it (the
/// strict mainnet policy must remain the secure default).
/// @dev Side-channel protection is achieved through mandatory instance expiry (INSTANCE_EXPIRY),
/// requiring periodic re-attestation with new keypairs.
/// @custom:security-contact security@taiko.xyz
abstract contract SgxVerifier is IProofVerifier, Ownable2Step {
/// @dev Each public-private key pair (Ethereum address) is generated within
/// the SGX program when it boots up. The off-chain remote attestation
/// ensures the validity of the program hash and has the capability of
/// bootstrapping the network with trustworthy instances.
struct Instance {
address addr;
uint64 validSince;
}
/// @notice The expiry time for the SGX instance.
uint64 public constant INSTANCE_EXPIRY = 365 days;
/// @notice A security feature, a delay until an instance is enabled when using onchain RA
/// verification
uint64 public constant INSTANCE_VALIDITY_DELAY = 0;
/// @dev SGX ATTRIBUTES.FLAGS bits that production application enclaves must not set. In DCAP
/// quote bytes, FLAGS is little-endian, so these bits are encoded in the first byte of the
/// 16-byte attributes field. This is enforced uniformly on every network (it is NOT part of the
/// per-network policy): a debug/provisioning enclave must never be trusted on-chain.
/// DEBUG(0x02): host can read/write enclave memory.
/// PROVISION_KEY(0x10): enclave can derive platform-identifying provisioning keys.
bytes16 private constant SGX_FORBIDDEN_ATTRIBUTE_MASK =
bytes16(0x12000000000000000000000000000000);
uint64 public immutable taikoChainId;
address public immutable automataDcapAttestation;
/// @notice The address authorized to register SGX instances via `registerInstance`.
/// @dev If set to a non-zero address, only this address may call `registerInstance`.
/// If set to `address(0)`, `registerInstance` is permissionless and callable by anyone.
address public immutable registrar;
/// @dev For gas savings, we assign each SGX instance with an ID to minimize storage operations.
/// Slot 1.
uint256 public nextInstanceId;
/// @dev One SGX instance is uniquely identified (on-chain) by its ECDSA public key
/// (or rather ethereum address). The instance address remains valid for INSTANCE_EXPIRY
/// duration (365 days) to protect against side-channel attacks through forced key expiry.
/// After expiry, the instance must be re-attested and registered with a new address.
/// Slot 2.
mapping(uint256 instanceId => Instance instance) public instances;
/// @dev One address shall be registered (during attestation) only once, otherwise it could
/// bypass this contract's expiry check by always registering with the same attestation and
/// getting multiple valid instanceIds.
/// Slot 3.
mapping(address instanceAddress => bool alreadyAttested) public addressRegistered;
uint256[47] private __gap;
/// @notice Emitted when a new SGX instance is added to the registry.
/// @param id The ID of the SGX instance.
/// @param instance The address of the SGX instance.
/// @param replaced Reserved for future use (always zero address).
/// @param validSince The time since the instance is valid.
event InstanceAdded(
uint256 indexed id, address indexed instance, address indexed replaced, uint256 validSince
);
/// @notice Emitted when an SGX instance is deleted from the registry.
/// @param id The ID of the SGX instance.
/// @param instance The address of the SGX instance.
event InstanceDeleted(uint256 indexed id, address indexed instance);
error SGX_ALREADY_ATTESTED();
error SGX_INVALID_ATTESTATION();
error SGX_INVALID_INSTANCE();
error SGX_INVALID_PROOF();
error SGX_INVALID_CHAIN_ID();
error SGX_FORBIDDEN_ATTRIBUTES();
error SGX_INVALID_TCB_STATUS();
error SGX_NOT_REGISTRAR();
constructor(
uint64 _taikoChainId,
address _owner,
address _automataDcapAttestation,
address _registrar
) {
require(_taikoChainId != 0, SGX_INVALID_CHAIN_ID());
taikoChainId = _taikoChainId;
automataDcapAttestation = _automataDcapAttestation;
registrar = _registrar;
_transferOwnership(_owner);
}
/// @notice Adds trusted SGX instances to the registry.
/// @param _instances The address array of trusted SGX instances.
/// @return The respective instanceId array per addresses.
function addInstances(address[] calldata _instances)
external
onlyOwner
returns (uint256[] memory)
{
return _addInstances(_instances, true);
}
/// @notice Deletes SGX instances from the registry.
/// @param _ids The ids array of SGX instances.
function deleteInstances(uint256[] calldata _ids) external onlyOwner {
uint256 size = _ids.length;
for (uint256 i; i < size; ++i) {
uint256 idx = _ids[i];
require(instances[idx].addr != address(0), SGX_INVALID_INSTANCE());
emit InstanceDeleted(idx, instances[idx].addr);
delete instances[idx];
}
}
/// @notice Adds an SGX instance after the attestation is verified
/// @param _attestation The parsed attestation quote.
/// @return The respective instanceId
function registerInstance(V3Struct.ParsedV3QuoteStruct calldata _attestation)
external
returns (uint256)
{
require(registrar == address(0) || msg.sender == registrar, SGX_NOT_REGISTRAR());
(bool verified, bytes memory retData) =
IAttestation(automataDcapAttestation).verifyParsedQuote(_attestation);
require(verified, SGX_INVALID_ATTESTATION());
// On a successful verification the attestation returns
// retData = abi.encodePacked(sha256(quote), uint8 tcbStatus), so the platform TCB status is
// the 33rd byte (offset 32). Enforce the per-network TCB-status policy on top of the
// attestation's own acceptance check.
require(retData.length >= 33, SGX_INVALID_ATTESTATION());
require(isTcbStatusAccepted(uint8(retData[32])), SGX_INVALID_TCB_STATUS());
require(
_attestation.localEnclaveReport.attributes & SGX_FORBIDDEN_ATTRIBUTE_MASK == bytes16(0),
SGX_FORBIDDEN_ATTRIBUTES()
);
address[] memory addresses = new address[](1);
addresses[0] = address(bytes20(_attestation.localEnclaveReport.reportData));
return _addInstances(addresses, false)[0];
}
/// @inheritdoc IProofVerifier
function verifyProof(
uint256, /* _proposalAge */
bytes32 _aggregatedProvingHash,
bytes calldata _proof
)
external
view
{
require(_proof.length == 89, SGX_INVALID_PROOF());
uint32 id = uint32(bytes4(_proof[:4]));
address instance = address(bytes20(_proof[4:24]));
require(_isInstanceValid(id, instance), SGX_INVALID_INSTANCE());
bytes32 signatureHash = LibPublicInput.hashPublicInputs(
_aggregatedProvingHash, address(this), instance, taikoChainId
);
// Verify the signature was created by the registered instance
bytes memory signature = _proof[24:];
require(instance == ECDSA.recover(signatureHash, signature), SGX_INVALID_PROOF());
}
/// @notice Returns whether a platform TCB status is accepted by this verifier's network policy.
/// @dev Defined by per-network subclasses. The platform TCB status is read from the attestation
/// output and expressed against the attestation's `TCBInfoStruct.TCBStatus` enum, so the on-chain
/// policy and the attestation cannot diverge and an enum reorder is caught at compile time. The
/// strict mainnet policy must remain the secure default.
/// @param _status The TCB status code from the attestation output.
/// @return Whether the status is accepted.
function isTcbStatusAccepted(uint8 _status) public pure virtual returns (bool);
function _addInstances(
address[] memory _instances,
bool instantValid
)
private
returns (uint256[] memory ids)
{
uint256 size = _instances.length;
ids = new uint256[](size);
uint64 validSince = uint64(block.timestamp);
if (!instantValid) {
validSince += INSTANCE_VALIDITY_DELAY;
}
for (uint256 i; i < size; ++i) {
require(!addressRegistered[_instances[i]], SGX_ALREADY_ATTESTED());
addressRegistered[_instances[i]] = true;
require(_instances[i] != address(0), SGX_INVALID_INSTANCE());
instances[nextInstanceId] = Instance(_instances[i], validSince);
ids[i] = nextInstanceId;
emit InstanceAdded(nextInstanceId, _instances[i], address(0), validSince);
++nextInstanceId;
}
}
function _isInstanceValid(uint256 id, address instance) private view returns (bool) {
require(instance != address(0), SGX_INVALID_INSTANCE());
require(instance == instances[id].addr, SGX_INVALID_INSTANCE());
return instances[id].validSince <= block.timestamp
&& block.timestamp <= instances[id].validSince + INSTANCE_EXPIRY;
}
}
node_modules/@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
node_modules/@openzeppelin/contracts/access/Ownable2Step.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
node_modules/@openzeppelin/contracts/utils/Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(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) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
node_modules/@openzeppelin/contracts/utils/math/Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// 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.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @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);
}
}
}
node_modules/solady/src/utils/EfficientHashLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for efficiently performing keccak256 hashes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EfficientHashLib.sol)
/// @dev To avoid stack-too-deep, you can use:
/// ```
/// bytes32[] memory buffer = EfficientHashLib.malloc(10);
/// EfficientHashLib.set(buffer, 0, value0);
/// ..
/// EfficientHashLib.set(buffer, 9, value9);
/// bytes32 finalHash = EfficientHashLib.hash(buffer);
/// ```
library EfficientHashLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MALLOC-LESS HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `keccak256(abi.encode(v0))`.
function hash(bytes32 v0) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
result := keccak256(0x00, 0x20)
}
}
/// @dev Returns `keccak256(abi.encode(v0))`.
function hash(uint256 v0) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
result := keccak256(0x00, 0x20)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1))`.
function hash(bytes32 v0, bytes32 v1) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
mstore(0x20, v1)
result := keccak256(0x00, 0x40)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1))`.
function hash(uint256 v0, uint256 v1) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
mstore(0x20, v1)
result := keccak256(0x00, 0x40)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
result := keccak256(m, 0x60)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
function hash(uint256 v0, uint256 v1, uint256 v2) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
result := keccak256(m, 0x60)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
result := keccak256(m, 0x80)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
result := keccak256(m, 0x80)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
result := keccak256(m, 0xa0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
result := keccak256(m, 0xa0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4, bytes32 v5)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
result := keccak256(m, 0xc0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4, uint256 v5)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
result := keccak256(m, 0xc0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
result := keccak256(m, 0xe0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
result := keccak256(m, 0xe0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
result := keccak256(m, 0x100)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
result := keccak256(m, 0x100)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
result := keccak256(m, 0x120)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
result := keccak256(m, 0x120)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
result := keccak256(m, 0x140)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
result := keccak256(m, 0x140)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
result := keccak256(m, 0x160)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
result := keccak256(m, 0x160)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
result := keccak256(m, 0x180)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
result := keccak256(m, 0x180)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11,
bytes32 v12
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
result := keccak256(m, 0x1a0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11,
uint256 v12
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
result := keccak256(m, 0x1a0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11,
bytes32 v12,
bytes32 v13
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
mstore(add(m, 0x1a0), v13)
result := keccak256(m, 0x1c0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11,
uint256 v12,
uint256 v13
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
mstore(add(m, 0x1a0), v13)
result := keccak256(m, 0x1c0)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTES32 BUFFER HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`.
function hash(bytes32[] memory buffer) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := keccak256(add(buffer, 0x20), shl(5, mload(buffer)))
}
}
/// @dev Sets `buffer[i]` to `value`, without a bounds check.
/// Returns the `buffer` for function chaining.
function set(bytes32[] memory buffer, uint256 i, bytes32 value)
internal
pure
returns (bytes32[] memory)
{
/// @solidity memory-safe-assembly
assembly {
mstore(add(buffer, shl(5, add(1, i))), value)
}
return buffer;
}
/// @dev Sets `buffer[i]` to `value`, without a bounds check.
/// Returns the `buffer` for function chaining.
function set(bytes32[] memory buffer, uint256 i, uint256 value)
internal
pure
returns (bytes32[] memory)
{
/// @solidity memory-safe-assembly
assembly {
mstore(add(buffer, shl(5, add(1, i))), value)
}
return buffer;
}
/// @dev Returns `new bytes32[](n)`, without zeroing out the memory.
function malloc(uint256 n) internal pure returns (bytes32[] memory buffer) {
/// @solidity memory-safe-assembly
assembly {
buffer := mload(0x40)
mstore(buffer, n)
mstore(0x40, add(shl(5, add(1, n)), buffer))
}
}
/// @dev Frees memory that has been allocated for `buffer`.
/// No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`.
function free(bytes32[] memory buffer) internal pure {
/// @solidity memory-safe-assembly
assembly {
let n := mload(buffer)
mstore(shl(6, lt(iszero(n), eq(add(shl(5, add(1, n)), buffer), mload(0x40)))), buffer)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EQUALITY CHECKS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `a == abi.decode(b, (bytes32))`.
function eq(bytes32 a, bytes memory b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(eq(0x20, mload(b)), eq(a, mload(add(b, 0x20))))
}
}
/// @dev Returns `abi.decode(a, (bytes32)) == a`.
function eq(bytes memory a, bytes32 b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(eq(0x20, mload(a)), eq(b, mload(add(a, 0x20))))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTE SLICE HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function hash(bytes memory b, uint256 start, uint256 end)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
end := xor(end, mul(xor(end, n), lt(n, end)))
start := xor(start, mul(xor(start, n), lt(n, start)))
result := keccak256(add(add(b, 0x20), start), mul(gt(end, start), sub(end, start)))
}
}
/// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
function hash(bytes memory b, uint256 start) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
start := xor(start, mul(xor(start, n), lt(n, start)))
result := keccak256(add(add(b, 0x20), start), mul(gt(n, start), sub(n, start)))
}
}
/// @dev Returns the keccak256 of the bytes.
function hash(bytes memory b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := keccak256(add(b, 0x20), mload(b))
}
}
/// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function hashCalldata(bytes calldata b, uint256 start, uint256 end)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(end, start), sub(end, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := keccak256(mload(0x40), n)
}
}
/// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
function hashCalldata(bytes calldata b, uint256 start) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(b.length, start), sub(b.length, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := keccak256(mload(0x40), n)
}
}
/// @dev Returns the keccak256 of the bytes.
function hashCalldata(bytes calldata b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
calldatacopy(mload(0x40), b.offset, b.length)
result := keccak256(mload(0x40), b.length)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SHA2-256 HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `sha256(abi.encode(b))`. Yes, it's more efficient.
function sha2(bytes32 b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, b)
result := mload(staticcall(gas(), 2, 0x00, 0x20, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function sha2(bytes memory b, uint256 start, uint256 end)
internal
view
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
end := xor(end, mul(xor(end, n), lt(n, end)))
start := xor(start, mul(xor(start, n), lt(n, start)))
// forgefmt: disable-next-item
result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
mul(gt(end, start), sub(end, start)), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
function sha2(bytes memory b, uint256 start) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
start := xor(start, mul(xor(start, n), lt(n, start)))
// forgefmt: disable-next-item
result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
mul(gt(n, start), sub(n, start)), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the bytes.
function sha2(bytes memory b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(staticcall(gas(), 2, add(b, 0x20), mload(b), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function sha2Calldata(bytes calldata b, uint256 start, uint256 end)
internal
view
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(end, start), sub(end, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
function sha2Calldata(bytes calldata b, uint256 start) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(b.length, start), sub(b.length, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the bytes.
function sha2Calldata(bytes calldata b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
calldatacopy(mload(0x40), b.offset, b.length)
result := mload(staticcall(gas(), 2, mload(0x40), b.length, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
}
Compiler Settings
{"viaIR":false,"remappings":["openzeppelin/=node_modules/@openzeppelin/","@openzeppelin/=node_modules/@openzeppelin/","@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/","@risc0/contracts/=node_modules/risc0-ethereum/contracts/src/","@solady/=node_modules/solady/","solady/src/=node_modules/solady/src/","solady/utils/=node_modules/solady/src/utils/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","ds-test/=node_modules/ds-test/","src/=contracts/","test/=test/","script/=script/","optimism/=node_modules/optimism/","p256-verifier/=node_modules/p256-verifier/","risc0-ethereum/=node_modules/risc0-ethereum/","sp1-contracts/=node_modules/sp1-contracts/","urc/=node_modules/urc/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"cancun"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint64","name":"_taikoChainId","internalType":"uint64"},{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_automataDcapAttestation","internalType":"address"},{"type":"address","name":"_registrar","internalType":"address"}]},{"type":"error","name":"InvalidAggregatedProvingHash","inputs":[]},{"type":"error","name":"SGX_ALREADY_ATTESTED","inputs":[]},{"type":"error","name":"SGX_FORBIDDEN_ATTRIBUTES","inputs":[]},{"type":"error","name":"SGX_INVALID_ATTESTATION","inputs":[]},{"type":"error","name":"SGX_INVALID_CHAIN_ID","inputs":[]},{"type":"error","name":"SGX_INVALID_INSTANCE","inputs":[]},{"type":"error","name":"SGX_INVALID_PROOF","inputs":[]},{"type":"error","name":"SGX_INVALID_TCB_STATUS","inputs":[]},{"type":"error","name":"SGX_NOT_REGISTRAR","inputs":[]},{"type":"event","name":"InstanceAdded","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":true},{"type":"address","name":"instance","internalType":"address","indexed":true},{"type":"address","name":"replaced","internalType":"address","indexed":true},{"type":"uint256","name":"validSince","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InstanceDeleted","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":true},{"type":"address","name":"instance","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"INSTANCE_EXPIRY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"INSTANCE_VALIDITY_DELAY","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"addInstances","inputs":[{"type":"address[]","name":"_instances","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"alreadyAttested","internalType":"bool"}],"name":"addressRegistered","inputs":[{"type":"address","name":"instanceAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"automataDcapAttestation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteInstances","inputs":[{"type":"uint256[]","name":"_ids","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"addr","internalType":"address"},{"type":"uint64","name":"validSince","internalType":"uint64"}],"name":"instances","inputs":[{"type":"uint256","name":"instanceId","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isTcbStatusAccepted","inputs":[{"type":"uint8","name":"_status","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextInstanceId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"registerInstance","inputs":[{"type":"tuple","name":"_attestation","internalType":"struct V3Struct.ParsedV3QuoteStruct","components":[{"type":"tuple","name":"header","internalType":"struct V3Struct.Header","components":[{"type":"bytes2","name":"version","internalType":"bytes2"},{"type":"bytes2","name":"attestationKeyType","internalType":"bytes2"},{"type":"bytes4","name":"teeType","internalType":"bytes4"},{"type":"bytes2","name":"qeSvn","internalType":"bytes2"},{"type":"bytes2","name":"pceSvn","internalType":"bytes2"},{"type":"bytes16","name":"qeVendorId","internalType":"bytes16"},{"type":"bytes20","name":"userData","internalType":"bytes20"}]},{"type":"tuple","name":"localEnclaveReport","internalType":"struct V3Struct.EnclaveReport","components":[{"type":"bytes16","name":"cpuSvn","internalType":"bytes16"},{"type":"bytes4","name":"miscSelect","internalType":"bytes4"},{"type":"bytes28","name":"reserved1","internalType":"bytes28"},{"type":"bytes16","name":"attributes","internalType":"bytes16"},{"type":"bytes32","name":"mrEnclave","internalType":"bytes32"},{"type":"bytes32","name":"reserved2","internalType":"bytes32"},{"type":"bytes32","name":"mrSigner","internalType":"bytes32"},{"type":"bytes","name":"reserved3","internalType":"bytes"},{"type":"uint16","name":"isvProdId","internalType":"uint16"},{"type":"uint16","name":"isvSvn","internalType":"uint16"},{"type":"bytes","name":"reserved4","internalType":"bytes"},{"type":"bytes","name":"reportData","internalType":"bytes"}]},{"type":"tuple","name":"v3AuthData","internalType":"struct V3Struct.ECDSAQuoteV3AuthData","components":[{"type":"bytes","name":"ecdsa256BitSignature","internalType":"bytes"},{"type":"bytes","name":"ecdsaAttestationKey","internalType":"bytes"},{"type":"tuple","name":"pckSignedQeReport","internalType":"struct V3Struct.EnclaveReport","components":[{"type":"bytes16","name":"cpuSvn","internalType":"bytes16"},{"type":"bytes4","name":"miscSelect","internalType":"bytes4"},{"type":"bytes28","name":"reserved1","internalType":"bytes28"},{"type":"bytes16","name":"attributes","internalType":"bytes16"},{"type":"bytes32","name":"mrEnclave","internalType":"bytes32"},{"type":"bytes32","name":"reserved2","internalType":"bytes32"},{"type":"bytes32","name":"mrSigner","internalType":"bytes32"},{"type":"bytes","name":"reserved3","internalType":"bytes"},{"type":"uint16","name":"isvProdId","internalType":"uint16"},{"type":"uint16","name":"isvSvn","internalType":"uint16"},{"type":"bytes","name":"reserved4","internalType":"bytes"},{"type":"bytes","name":"reportData","internalType":"bytes"}]},{"type":"bytes","name":"qeReportSignature","internalType":"bytes"},{"type":"tuple","name":"qeAuthData","internalType":"struct V3Struct.QEAuthData","components":[{"type":"uint16","name":"parsedDataSize","internalType":"uint16"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"tuple","name":"certification","internalType":"struct V3Struct.CertificationData","components":[{"type":"uint16","name":"certType","internalType":"uint16"},{"type":"uint32","name":"certDataSize","internalType":"uint32"},{"type":"bytes[3]","name":"decodedCertDataArray","internalType":"bytes[3]"}]}]}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"registrar","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"taikoChainId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"verifyProof","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes32","name":"_aggregatedProvingHash","internalType":"bytes32"},{"type":"bytes","name":"_proof","internalType":"bytes"}]}]
Contract Creation Code
0x60e060405234801561000f575f5ffd5b50604051611b86380380611b8683398101604081905261002e91610120565b8383838361003b3361009a565b836001600160401b03165f036100645760405163759159ef60e11b815260040160405180910390fd5b6001600160401b0384166080526001600160a01b0380831660a052811660c05261008d8361009a565b505050505050505061017e565b600180546001600160a01b03191690556100b3816100b6565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461011b575f5ffd5b919050565b5f5f5f5f60808587031215610133575f5ffd5b84516001600160401b0381168114610149575f5ffd5b935061015760208601610105565b925061016560408601610105565b915061017360608601610105565b905092959194509250565b60805160a05160c0516119c26101c45f395f81816101580152818161062e015261066801525f818161019701526106ab01525f818161028401526103c101526119c25ff3fe608060405234801561000f575f5ffd5b5060043610610111575f3560e01c8063a2f7b3a51161009e578063d632cf351161006e578063d632cf35146102e6578063e16e8218146102f1578063e30c397814610304578063ee45abb014610315578063f2fde38b1461031e575f5ffd5b8063a2f7b3a51461021e578063a5a1d0c51461027f578063a91951a2146102be578063b51ec328146102df575f5ffd5b80634ef36a56116100e45780634ef36a56146101b9578063715018a6146101cc57806379ba5097146101d45780638da5cb5b146101dc5780639d7809b5146101ec575f5ffd5b806314bcf3dd14610115578063161072901461012a5780632b20e3971461015357806336383dc714610192575b5f5ffd5b610128610123366004611052565b610331565b005b61013d61013836600461110c565b610473565b60405161014a919061114a565b60405180910390f35b61017a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161014a565b61017a7f000000000000000000000000000000000000000000000000000000000000000081565b6101286101c736600461110c565b6104c4565b610128610599565b6101286105ac565b5f546001600160a01b031661017a565b61020e6101fa36600461118c565b60046020525f908152604090205460ff1681565b604051901515815260200161014a565b61025861022c3660046111b9565b60036020525f90815260409020546001600160a01b03811690600160a01b90046001600160401b031682565b604080516001600160a01b0390931683526001600160401b0390911660208301520161014a565b6102a67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b03909116815260200161014a565b6102d16102cc3660046111d0565b61062b565b60405190815260200161014a565b6102a65f81565b6102a66301e1338081565b61020e6102ff366004611207565b6108ba565b6001546001600160a01b031661017a565b6102d160025481565b61012861032c36600461118c565b6108de565b6059811461035257604051637bb2c12960e01b815260040160405180910390fd5b5f6103606004828486611227565b6103699161124e565b60e01c90505f61037d601860048587611227565b61038691611286565b60601c905061039b8263ffffffff168261094e565b6103b857604051630c3bd7cd60e11b815260040160405180910390fd5b5f6103e58630847f0000000000000000000000000000000000000000000000000000000000000000610a18565b90505f6103f58560188189611227565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509293506104389250849150839050610a8b565b6001600160a01b0316836001600160a01b03161461046957604051637bb2c12960e01b815260040160405180910390fd5b5050505050505050565b606061047d610aad565b6104bb8383808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525060019250610b06915050565b90505b92915050565b6104cc610aad565b805f5b81811015610593575f8484838181106104ea576104ea6112bc565b602090810292909201355f8181526003909352604090922054919250506001600160a01b031661052d57604051630c3bd7cd60e11b815260040160405180910390fd5b5f818152600360205260408082205490516001600160a01b039091169183917f89d0dca869ffe08b709ca9ff5adfd5ee8d9de2750d0561e15df614c7a2596d8e9190a35f90815260036020526040902080546001600160e01b03191690556001016104cf565b50505050565b6105a1610aad565b6105aa5f610da2565b565b60015433906001600160a01b0316811461061f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61062881610da2565b50565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158061068a5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6106a75760405163ae79e77d60e01b815260040160405180910390fd5b5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663089a168f856040518263ffffffff1660e01b81526004016106f591906116d3565b5f604051808303815f875af1158015610710573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261073791908101906117eb565b915091508161075957604051631cbfe78f60e21b815260040160405180910390fd5b60218151101561077c57604051631cbfe78f60e21b815260040160405180910390fd5b61079f81602081518110610792576107926112bc565b016020015160f81c6108ba565b6107bc5760405163266eb4b760e01b815260040160405180910390fd5b5f600960f91b6107cf60e08701876118b3565b6107e09060808101906060016118d2565b166fffffffffffffffffffffffffffffffff19161461081257604051631e9271af60e31b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833701905050905061084060e08601866118b3565b61084f906101608101906118eb565b61085891611286565b60601c815f8151811061086d5761086d6112bc565b60200260200101906001600160a01b031690816001600160a01b031681525050610897815f610b06565b5f815181106108a8576108a86112bc565b60200260200101519350505050919050565b5f60ff821615806108ce575060ff82166001145b806104be57505060ff1660021490565b6108e6610aad565b600180546001600160a01b0383166001600160a01b031990911681179091556109165f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160a01b03821661097657604051630c3bd7cd60e11b815260040160405180910390fd5b5f838152600360205260409020546001600160a01b038381169116146109af57604051630c3bd7cd60e11b815260040160405180910390fd5b5f8381526003602052604090205442600160a01b9091046001600160401b0316118015906104bb57505f83815260036020526040902054610a05906301e1338090600160a01b90046001600160401b0316611955565b6001600160401b03164211159392505050565b5f84610a37576040516318e48a7560e21b815260040160405180910390fd5b604080516b2b22a924a32cafa82927a7a360a11b81526001600160401b03841660208201526001600160a01b038681169282019290925260608101879052908416608082015260a090205b95945050505050565b5f5f5f610a988585610dbb565b91509150610aa581610dfd565b509392505050565b5f546001600160a01b031633146105aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610616565b8151606090806001600160401b03811115610b2357610b236117d7565b604051908082528060200260200182016040528015610b4c578160200160208202803683370190505b5091504283610b6257610b5f5f82611955565b90505b5f5b82811015610d995760045f878381518110610b8157610b816112bc565b6020908102919091018101516001600160a01b031682528101919091526040015f205460ff1615610bc55760405163a239527960e01b815260040160405180910390fd5b600160045f888481518110610bdc57610bdc6112bc565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f6001600160a01b0316868281518110610c3557610c356112bc565b60200260200101516001600160a01b031603610c6457604051630c3bd7cd60e11b815260040160405180910390fd5b6040518060400160405280878381518110610c8157610c816112bc565b6020908102919091018101516001600160a01b0390811683526001600160401b0380871693830193909352600280545f9081526003845260409020855181549690940151909416600160a01b026001600160e01b03199095169290911691909117929092179055548451859083908110610cfd57610cfd6112bc565b6020026020010181815250505f6001600160a01b0316868281518110610d2557610d256112bc565b60200260200101516001600160a01b03166002547fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb85604051610d7791906001600160401b0391909116815260200190565b60405180910390a460025f8154610d8d90611974565b90915550600101610b64565b50505092915050565b600180546001600160a01b031916905561062881610f46565b5f5f8251604103610def576020830151604084015160608501515f1a610de387828585610f95565b94509450505050610df6565b505f905060025b9250929050565b5f816004811115610e1057610e1061192d565b03610e185750565b6001816004811115610e2c57610e2c61192d565b03610e795760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610616565b6002816004811115610e8d57610e8d61192d565b03610eda5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610616565b6003816004811115610eee57610eee61192d565b036106285760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610616565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610fca57505f90506003611049565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561101b573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116611043575f60019250925050611049565b91505f90505b94509492505050565b5f5f5f5f60608587031215611065575f5ffd5b843593506020850135925060408501356001600160401b03811115611088575f5ffd5b8501601f81018713611098575f5ffd5b80356001600160401b038111156110ad575f5ffd5b8760208284010111156110be575f5ffd5b949793965060200194505050565b5f5f83601f8401126110dc575f5ffd5b5081356001600160401b038111156110f2575f5ffd5b6020830191508360208260051b8501011115610df6575f5ffd5b5f5f6020838503121561111d575f5ffd5b82356001600160401b03811115611132575f5ffd5b61113e858286016110cc565b90969095509350505050565b602080825282518282018190525f918401906040840190835b81811015611181578351835260209384019390920191600101611163565b509095945050505050565b5f6020828403121561119c575f5ffd5b81356001600160a01b03811681146111b2575f5ffd5b9392505050565b5f602082840312156111c9575f5ffd5b5035919050565b5f602082840312156111e0575f5ffd5b81356001600160401b038111156111f5575f5ffd5b820161012081850312156111b2575f5ffd5b5f60208284031215611217575f5ffd5b813560ff811681146111b2575f5ffd5b5f5f85851115611235575f5ffd5b83861115611241575f5ffd5b5050820193919092039150565b80356001600160e01b0319811690600484101561127f576001600160e01b0319600485900360031b81901b82161691505b5092915050565b80356001600160601b0319811690601484101561127f576001600160601b031960149490940360031b84901b1690921692915050565b634e487b7160e01b5f52603260045260245ffd5b80356001600160f01b0319811681146112e7575f5ffd5b919050565b80356001600160e01b0319811681146112e7575f5ffd5b80356001600160801b0319811681146112e7575f5ffd5b80356001600160601b0319811681146112e7575f5ffd5b5f823561017e19833603018112611346575f5ffd5b90910192915050565b803563ffffffff19811681146112e7575f5ffd5b5f5f8335601e19843603018112611378575f5ffd5b83016020810192503590506001600160401b03811115611396575f5ffd5b803603821315610df6575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b803561ffff811681146112e7575f5ffd5b6113f8826113ea83611303565b6001600160801b0319169052565b5f611405602083016112ec565b6001600160e01b03191660208401526114206040830161134f565b63ffffffff1916604084015261143860608301611303565b6001600160801b03191660608401526080828101359084015260a0808301359084015260c0808301359084015261147260e0830183611363565b61018060e0860152611489610180860182846113a4565b91505061149961010084016113cc565b61ffff166101008501526114b061012084016113cc565b61ffff166101208501526114c8610140840184611363565b8583036101408701526114dc8382846113a4565b925050506114ee610160840184611363565b8583036101608701526115028382846113a4565b9695505050505050565b5f823560be19833603018112611346575f5ffd5b61ffff61152c826113cc565b1682525f61153d6020830183611363565b60406020860152610a826040860182846113a4565b5f8235605e19833603018112611346575f5ffd5b5f6060830161ffff611577846113cc565b168452602083013563ffffffff8116808214611591575f5ffd5b6020860152506115a46040840184611552565b6060604086015260c0850191815f5b60038110156115f157878503605f190183526115cf8285611363565b6115da8782846113a4565b9650505060209283019291909101906001016115b3565b50929695505050505050565b5f6116088283611363565b60c0855261161a60c0860182846113a4565b91505061162a6020840184611363565b858303602087015261163d8382846113a4565b9250505061164e6040840184611331565b848203604086015261166082826113dd565b9150506116706060840184611363565b85830360608701526116838382846113a4565b925050506080830135603e1984360301811261169d575f5ffd5b84820360808601526116b182858301611520565b9150506116c160a0840184611552565b84820360a0860152610a828282611566565b602081526001600160f01b03196116e9836112d0565b16602082015261ffff60f01b611701602084016112d0565b16604082015263ffffffff60e01b61171b604084016112ec565b16606082015261ffff60f01b611733606084016112d0565b16608082015261ffff60f01b61174b608084016112d0565b1660a08201525f61175e60a08401611303565b6001600160801b0319811660c08401525061177b60c0840161131a565b6001600160601b0319811660e08401525061179960e0840184611331565b6101206101008401526117b06101408401826113dd565b90506117c061010085018561150c565b838203601f1901610120850152610a8282826115fd565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156117fc575f5ffd5b8251801515811461180b575f5ffd5b60208401519092506001600160401b03811115611826575f5ffd5b8301601f81018513611836575f5ffd5b80516001600160401b0381111561184f5761184f6117d7565b604051601f8201601f19908116603f011681016001600160401b038111828210171561187d5761187d6117d7565b604052818152828201602001871015611894575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f823561017e198336030181126118c8575f5ffd5b9190910192915050565b5f602082840312156118e2575f5ffd5b6104bb82611303565b5f5f8335601e19843603018112611900575f5ffd5b8301803591506001600160401b03821115611919575f5ffd5b602001915036819003821315610df6575f5ffd5b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908111156104be576104be611941565b5f6001820161198557611985611941565b506001019056fea26469706673582212209925ec1b645b83908d0739596de4d034207e564a78d508cdbdff1e829e0cbba164736f6c634300081e00330000000000000000000000000000000000000000000000000000000000028c590000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b8000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e0000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b8
Deployed ByteCode
0x608060405234801561000f575f5ffd5b5060043610610111575f3560e01c8063a2f7b3a51161009e578063d632cf351161006e578063d632cf35146102e6578063e16e8218146102f1578063e30c397814610304578063ee45abb014610315578063f2fde38b1461031e575f5ffd5b8063a2f7b3a51461021e578063a5a1d0c51461027f578063a91951a2146102be578063b51ec328146102df575f5ffd5b80634ef36a56116100e45780634ef36a56146101b9578063715018a6146101cc57806379ba5097146101d45780638da5cb5b146101dc5780639d7809b5146101ec575f5ffd5b806314bcf3dd14610115578063161072901461012a5780632b20e3971461015357806336383dc714610192575b5f5ffd5b610128610123366004611052565b610331565b005b61013d61013836600461110c565b610473565b60405161014a919061114a565b60405180910390f35b61017a7f0000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b881565b6040516001600160a01b03909116815260200161014a565b61017a7f000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e81565b6101286101c736600461110c565b6104c4565b610128610599565b6101286105ac565b5f546001600160a01b031661017a565b61020e6101fa36600461118c565b60046020525f908152604090205460ff1681565b604051901515815260200161014a565b61025861022c3660046111b9565b60036020525f90815260409020546001600160a01b03811690600160a01b90046001600160401b031682565b604080516001600160a01b0390931683526001600160401b0390911660208301520161014a565b6102a67f0000000000000000000000000000000000000000000000000000000000028c5981565b6040516001600160401b03909116815260200161014a565b6102d16102cc3660046111d0565b61062b565b60405190815260200161014a565b6102a65f81565b6102a66301e1338081565b61020e6102ff366004611207565b6108ba565b6001546001600160a01b031661017a565b6102d160025481565b61012861032c36600461118c565b6108de565b6059811461035257604051637bb2c12960e01b815260040160405180910390fd5b5f6103606004828486611227565b6103699161124e565b60e01c90505f61037d601860048587611227565b61038691611286565b60601c905061039b8263ffffffff168261094e565b6103b857604051630c3bd7cd60e11b815260040160405180910390fd5b5f6103e58630847f0000000000000000000000000000000000000000000000000000000000028c59610a18565b90505f6103f58560188189611227565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509293506104389250849150839050610a8b565b6001600160a01b0316836001600160a01b03161461046957604051637bb2c12960e01b815260040160405180910390fd5b5050505050505050565b606061047d610aad565b6104bb8383808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525060019250610b06915050565b90505b92915050565b6104cc610aad565b805f5b81811015610593575f8484838181106104ea576104ea6112bc565b602090810292909201355f8181526003909352604090922054919250506001600160a01b031661052d57604051630c3bd7cd60e11b815260040160405180910390fd5b5f818152600360205260408082205490516001600160a01b039091169183917f89d0dca869ffe08b709ca9ff5adfd5ee8d9de2750d0561e15df614c7a2596d8e9190a35f90815260036020526040902080546001600160e01b03191690556001016104cf565b50505050565b6105a1610aad565b6105aa5f610da2565b565b60015433906001600160a01b0316811461061f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61062881610da2565b50565b5f7f0000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b86001600160a01b0316158061068a5750336001600160a01b037f0000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b816145b6106a75760405163ae79e77d60e01b815260040160405180910390fd5b5f5f7f000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e6001600160a01b031663089a168f856040518263ffffffff1660e01b81526004016106f591906116d3565b5f604051808303815f875af1158015610710573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261073791908101906117eb565b915091508161075957604051631cbfe78f60e21b815260040160405180910390fd5b60218151101561077c57604051631cbfe78f60e21b815260040160405180910390fd5b61079f81602081518110610792576107926112bc565b016020015160f81c6108ba565b6107bc5760405163266eb4b760e01b815260040160405180910390fd5b5f600960f91b6107cf60e08701876118b3565b6107e09060808101906060016118d2565b166fffffffffffffffffffffffffffffffff19161461081257604051631e9271af60e31b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833701905050905061084060e08601866118b3565b61084f906101608101906118eb565b61085891611286565b60601c815f8151811061086d5761086d6112bc565b60200260200101906001600160a01b031690816001600160a01b031681525050610897815f610b06565b5f815181106108a8576108a86112bc565b60200260200101519350505050919050565b5f60ff821615806108ce575060ff82166001145b806104be57505060ff1660021490565b6108e6610aad565b600180546001600160a01b0383166001600160a01b031990911681179091556109165f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160a01b03821661097657604051630c3bd7cd60e11b815260040160405180910390fd5b5f838152600360205260409020546001600160a01b038381169116146109af57604051630c3bd7cd60e11b815260040160405180910390fd5b5f8381526003602052604090205442600160a01b9091046001600160401b0316118015906104bb57505f83815260036020526040902054610a05906301e1338090600160a01b90046001600160401b0316611955565b6001600160401b03164211159392505050565b5f84610a37576040516318e48a7560e21b815260040160405180910390fd5b604080516b2b22a924a32cafa82927a7a360a11b81526001600160401b03841660208201526001600160a01b038681169282019290925260608101879052908416608082015260a090205b95945050505050565b5f5f5f610a988585610dbb565b91509150610aa581610dfd565b509392505050565b5f546001600160a01b031633146105aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610616565b8151606090806001600160401b03811115610b2357610b236117d7565b604051908082528060200260200182016040528015610b4c578160200160208202803683370190505b5091504283610b6257610b5f5f82611955565b90505b5f5b82811015610d995760045f878381518110610b8157610b816112bc565b6020908102919091018101516001600160a01b031682528101919091526040015f205460ff1615610bc55760405163a239527960e01b815260040160405180910390fd5b600160045f888481518110610bdc57610bdc6112bc565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f6001600160a01b0316868281518110610c3557610c356112bc565b60200260200101516001600160a01b031603610c6457604051630c3bd7cd60e11b815260040160405180910390fd5b6040518060400160405280878381518110610c8157610c816112bc565b6020908102919091018101516001600160a01b0390811683526001600160401b0380871693830193909352600280545f9081526003845260409020855181549690940151909416600160a01b026001600160e01b03199095169290911691909117929092179055548451859083908110610cfd57610cfd6112bc565b6020026020010181815250505f6001600160a01b0316868281518110610d2557610d256112bc565b60200260200101516001600160a01b03166002547fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb85604051610d7791906001600160401b0391909116815260200190565b60405180910390a460025f8154610d8d90611974565b90915550600101610b64565b50505092915050565b600180546001600160a01b031916905561062881610f46565b5f5f8251604103610def576020830151604084015160608501515f1a610de387828585610f95565b94509450505050610df6565b505f905060025b9250929050565b5f816004811115610e1057610e1061192d565b03610e185750565b6001816004811115610e2c57610e2c61192d565b03610e795760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610616565b6002816004811115610e8d57610e8d61192d565b03610eda5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610616565b6003816004811115610eee57610eee61192d565b036106285760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610616565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610fca57505f90506003611049565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561101b573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116611043575f60019250925050611049565b91505f90505b94509492505050565b5f5f5f5f60608587031215611065575f5ffd5b843593506020850135925060408501356001600160401b03811115611088575f5ffd5b8501601f81018713611098575f5ffd5b80356001600160401b038111156110ad575f5ffd5b8760208284010111156110be575f5ffd5b949793965060200194505050565b5f5f83601f8401126110dc575f5ffd5b5081356001600160401b038111156110f2575f5ffd5b6020830191508360208260051b8501011115610df6575f5ffd5b5f5f6020838503121561111d575f5ffd5b82356001600160401b03811115611132575f5ffd5b61113e858286016110cc565b90969095509350505050565b602080825282518282018190525f918401906040840190835b81811015611181578351835260209384019390920191600101611163565b509095945050505050565b5f6020828403121561119c575f5ffd5b81356001600160a01b03811681146111b2575f5ffd5b9392505050565b5f602082840312156111c9575f5ffd5b5035919050565b5f602082840312156111e0575f5ffd5b81356001600160401b038111156111f5575f5ffd5b820161012081850312156111b2575f5ffd5b5f60208284031215611217575f5ffd5b813560ff811681146111b2575f5ffd5b5f5f85851115611235575f5ffd5b83861115611241575f5ffd5b5050820193919092039150565b80356001600160e01b0319811690600484101561127f576001600160e01b0319600485900360031b81901b82161691505b5092915050565b80356001600160601b0319811690601484101561127f576001600160601b031960149490940360031b84901b1690921692915050565b634e487b7160e01b5f52603260045260245ffd5b80356001600160f01b0319811681146112e7575f5ffd5b919050565b80356001600160e01b0319811681146112e7575f5ffd5b80356001600160801b0319811681146112e7575f5ffd5b80356001600160601b0319811681146112e7575f5ffd5b5f823561017e19833603018112611346575f5ffd5b90910192915050565b803563ffffffff19811681146112e7575f5ffd5b5f5f8335601e19843603018112611378575f5ffd5b83016020810192503590506001600160401b03811115611396575f5ffd5b803603821315610df6575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b803561ffff811681146112e7575f5ffd5b6113f8826113ea83611303565b6001600160801b0319169052565b5f611405602083016112ec565b6001600160e01b03191660208401526114206040830161134f565b63ffffffff1916604084015261143860608301611303565b6001600160801b03191660608401526080828101359084015260a0808301359084015260c0808301359084015261147260e0830183611363565b61018060e0860152611489610180860182846113a4565b91505061149961010084016113cc565b61ffff166101008501526114b061012084016113cc565b61ffff166101208501526114c8610140840184611363565b8583036101408701526114dc8382846113a4565b925050506114ee610160840184611363565b8583036101608701526115028382846113a4565b9695505050505050565b5f823560be19833603018112611346575f5ffd5b61ffff61152c826113cc565b1682525f61153d6020830183611363565b60406020860152610a826040860182846113a4565b5f8235605e19833603018112611346575f5ffd5b5f6060830161ffff611577846113cc565b168452602083013563ffffffff8116808214611591575f5ffd5b6020860152506115a46040840184611552565b6060604086015260c0850191815f5b60038110156115f157878503605f190183526115cf8285611363565b6115da8782846113a4565b9650505060209283019291909101906001016115b3565b50929695505050505050565b5f6116088283611363565b60c0855261161a60c0860182846113a4565b91505061162a6020840184611363565b858303602087015261163d8382846113a4565b9250505061164e6040840184611331565b848203604086015261166082826113dd565b9150506116706060840184611363565b85830360608701526116838382846113a4565b925050506080830135603e1984360301811261169d575f5ffd5b84820360808601526116b182858301611520565b9150506116c160a0840184611552565b84820360a0860152610a828282611566565b602081526001600160f01b03196116e9836112d0565b16602082015261ffff60f01b611701602084016112d0565b16604082015263ffffffff60e01b61171b604084016112ec565b16606082015261ffff60f01b611733606084016112d0565b16608082015261ffff60f01b61174b608084016112d0565b1660a08201525f61175e60a08401611303565b6001600160801b0319811660c08401525061177b60c0840161131a565b6001600160601b0319811660e08401525061179960e0840184611331565b6101206101008401526117b06101408401826113dd565b90506117c061010085018561150c565b838203601f1901610120850152610a8282826115fd565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156117fc575f5ffd5b8251801515811461180b575f5ffd5b60208401519092506001600160401b03811115611826575f5ffd5b8301601f81018513611836575f5ffd5b80516001600160401b0381111561184f5761184f6117d7565b604051601f8201601f19908116603f011681016001600160401b038111828210171561187d5761187d6117d7565b604052818152828201602001871015611894575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f823561017e198336030181126118c8575f5ffd5b9190910192915050565b5f602082840312156118e2575f5ffd5b6104bb82611303565b5f5f8335601e19843603018112611900575f5ffd5b8301803591506001600160401b03821115611919575f5ffd5b602001915036819003821315610df6575f5ffd5b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908111156104be576104be611941565b5f6001820161198557611985611941565b506001019056fea26469706673582212209925ec1b645b83908d0739596de4d034207e564a78d508cdbdff1e829e0cbba164736f6c634300081e0033