Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SgxVerifier
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- prague
- Verified at
- 2025-12-15T12:46:46.411982Z
Constructor Arguments
0x0000000000000000000000000000000000000000000000000000000000028c590000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b800000000000000000000000018a235e18bee9cda516f227aa97ae6627e7d612c
Arg [0] (uint64) : 167001
Arg [1] (address) : 0x4779d18931b35540f84b0cd0e9633855b84df7b8
Arg [2] (address) : 0x18a235e18bee9cda516f227aa97ae6627e7d612c
contracts/layer1/verifiers/SgxVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
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 This contract verifies SGX signature proofs onchain using attested SGX instances.
/// Each instance is registered via remote attestation and can verify proofs until expiry.
/// @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
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;
uint64 public immutable taikoChainId;
address public immutable automataDcapAttestation;
/// @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();
constructor(uint64 _taikoChainId, address _owner, address _automataDcapAttestation) {
require(_taikoChainId != 0, SGX_INVALID_CHAIN_ID());
taikoChainId = _taikoChainId;
automataDcapAttestation = _automataDcapAttestation;
_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)
{
(bool verified,) = IAttestation(automataDcapAttestation).verifyParsedQuote(_attestation);
require(verified, SGX_INVALID_ATTESTATION());
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());
}
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;
}
}
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/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.24;
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();
}
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/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;
}
}
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":true,"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":{"contracts/layer1/core/libs/LibInboxSetup.sol":{"LibInboxSetup":"0xf88Ef5437749A225621101BE8C1BE1A0cE967758"},"contracts/layer1/core/libs/LibForcedInclusion.sol":{"LibForcedInclusion":"0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14"}},"evmVersion":"prague"}
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":"error","name":"InvalidAggregatedProvingHash","inputs":[]},{"type":"error","name":"SGX_ALREADY_ATTESTED","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":"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":"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":"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
0x60c0346100c657601f61131e38819003918201601f19168301916001600160401b038311848410176100ca578084926060946040528339810103126100c6578051906001600160401b0382168083036100c65761006a6040610063602085016100de565b93016100de565b90610074336100f2565b156100b7576100889260805260a0526100f2565b6040516111d7908161014782396080518181816108010152610de3015260a05181818161044f0152610ac20152f35b63759159ef60e11b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036100c657565b600180546001600160a01b03199081169091555f80546001600160a01b03938416928116831782559192909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a356fe6080806040526004361015610012575f80fd5b5f3560e01c90816314bcf3dd14610d4b575080631610729014610af157806336383dc714610aad5780634ef36a56146109f7578063715018a61461099457806379ba5097146108cb5780638da5cb5b146108a45780639d7809b514610867578063a2f7b3a514610825578063a5a1d0c5146107e2578063a91951a2146101ba578063b51ec328146101a0578063d632cf3514610182578063e30c39781461015a578063ee45abb01461013d5763f2fde38b146100cc575f80fd5b34610139576020366003190112610139576100e5610e9c565b6100ed61114a565b60018060a01b0316806001600160601b0360a01b600154161760015560018060a01b035f54167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b5f80fd5b34610139575f366003190112610139576020600254604051908152f35b34610139575f366003190112610139576001546040516001600160a01b039091168152602090f35b34610139575f3660031901126101395760206040516301e133808152f35b34610139575f3660031901126101395760206040515f8152f35b34610139576020366003190112610139576004356001600160401b0381116101395780600401908036036101206003198201126101395760405163089a168f60e01b8152602060048201526001600160f01b031961021785610f34565b16602482015261ffff60f01b61022f60248501610f34565b16604482015263ffffffff60e01b61024960448501610f49565b16606482015261ffff60f01b61026160648501610f34565b16608482015261ffff60f01b61027960848501610f34565b1660a48201526001600160801b031961029460a48501610f5e565b1660c482015260c48301356001600160601b031981168091036101395760e48201526102db6102c760e485018096610f73565b610120610104840152610144830190610fe8565b61010484013560c2198401811215610139578282036023190161012484015284016004810161037461035961033f6103246103168580610f88565b60c0895260c0890191610fb9565b6103316024870186610f88565b9088830360208a0152610fb9565b61034c6044860185610f73565b8682036040880152610fe8565b6103666064850184610f88565b908683036060880152610fb9565b608483013591906042193685900301831215610139576103cf60a49160406103bf6004886103d798010189840360808b015261ffff6103b282610fd9565b1684526020810190610f88565b9190928160208201520191610fb9565b930190611101565b9160a0818303910152606081019161ffff6103f182610fd9565b16825260208101359063ffffffff82168092036101395761041f908392602087969501526040810190611101565b91606060408301529060c081019280925f915b600383106107a857505050505090805f9203818360018060a01b037f0000000000000000000000000000000000000000000000000000000000000000165af190811561079d575f91610718575b5015610709576040918251936104958486610ee1565b60018552601f198401366020870137359161018219018212156101395701610164810135602219368390030181121561013957016004018035906001600160401b0382116101395760200181360381136101395735906001600160601b0319821691601482106106e4575b505060601c61050e83611115565b52815161051a81610f1d565b9061052783519283610ee1565b808252601f1961053682610f1d565b013660208401376001600160401b034216806001600160401b0381116106b257505f5b8281106105745760208561056c86611115565b519051908152f35b6001600160a01b036105868288611136565b51165f52600460205260ff855f2054166106d5576001600160a01b036105ac8288611136565b51165f9081526004602052859020805460ff191660011790556001600160a01b036105d78288611136565b5116156106c6576001600160a01b036105f08288611136565b51168551906105fe82610eb2565b81526020808201848152600280545f9081526003909352918890209251835491516001600160e01b03199092166001600160a01b03919091161760a09190911b67ffffffffffffffff60a01b161790915554908161065c8287611136565b525f6001600160a01b03610670838a611136565b5116837fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb60208a51888152a45f1982146106b257600180920160025501610559565b634e487b7160e01b5f52601160045260245ffd5b630c3bd7cd60e11b5f5260045ffd5b63a239527960e01b5f5260045ffd5b6bffffffffffffffffffffffff1960149290920360031b82901b161690508380610500565b631cbfe78f60e21b5f5260045ffd5b90503d805f833e6107298183610ee1565b8101604082820312610139578151918215158303610139576020810151906001600160401b038211610139570181601f8201121561013957805161076c81610f02565b9261077a6040519485610ee1565b81845260208284010111610139575f928160208094018483015e0101528461047f565b6040513d5f823e3d90fd5b9193955091936020806107d0600193605f198982030187526107ca8a87610f88565b90610fb9565b97019301930190928695949293610432565b34610139575f3660031901126101395760206040516001600160401b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610139576020366003190112610139576004355f5260036020526040805f20546001600160401b0382519160018060a01b038116835260a01c166020820152f35b34610139576020366003190112610139576001600160a01b03610888610e9c565b165f526004602052602060ff60405f2054166040519015158152f35b34610139575f366003190112610139575f546040516001600160a01b039091168152602090f35b34610139575f36600319011261013957600154336001600160a01b039091160361093d57600180546001600160a01b03199081169091555f805433928116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b34610139575f366003190112610139576109ac61114a565b600180546001600160a01b03199081169091555f80549182168155906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610139576020366003190112610139576004356001600160401b03811161013957610a27903690600401610e6c565b90610a3061114a565b5f5b82811015610aab578060051b82013590815f52600360205260018060a01b0360405f205416156106c657816001925f526003602052828060a01b0360405f205416817f89d0dca869ffe08b709ca9ff5adfd5ee8d9de2750d0561e15df614c7a2596d8e5f80a35f5260036020525f604081205501610a32565b005b34610139575f366003190112610139576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610139576020366003190112610139576004356001600160401b03811161013957610b21903690600401610e6c565b610b2961114a565b610b3281610f1d565b91610b406040519384610ee1565b818352602083019160051b81019036821161013957915b818310610d2b57835184610b6a82610f1d565b91610b786040519384610ee1565b808352610b8481610f1d565b602084019290601f19013684376001600160401b0342165f5b838110610be8578486604051918291602083019060208452518091526040830191905f5b818110610bcf575050500390f35b8251845285945060209384019390920191600101610bc1565b6001600160a01b03610bfa8285611136565b51165f52600460205260ff60405f2054166106d5576001600160a01b03610c218285611136565b51165f908152600460205260409020805460ff191660011790556001600160a01b03610c4d8285611136565b5116156106c6576001600160a01b03610c668285611136565b511660405190610c7582610eb2565b81526020808201848152600280545f908152600390935260409092209251835491516001600160e01b03199092166001600160a01b03919091161760a09190911b67ffffffffffffffff60a01b1617909155549081610cd48289611136565b525f6001600160a01b03610ce88387611136565b5116837fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb6020604051888152a45f1982146106b257600180920160025501610b9d565b82356001600160a01b038116810361013957815260209283019201610b57565b3461013957606036600319011261013957602435906044356001600160401b0381116101395736602382011215610139578060040135906001600160401b0382116101395736602483830101116101395760598203610e5d57816004116101395781601811610139576028810135928415610e4e5760806008945f966b2b22a924a32cafa82927a7a360a11b84526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166020850152306040850152606084015260018060a01b039060601c169101526017198201603c610e3282610f02565b92610e406040519485610ee1565b828452016020830137010152005b6318e48a7560e21b5f5260045ffd5b637bb2c12960e01b5f5260045ffd5b9181601f84011215610139578235916001600160401b038311610139576020808501948460051b01011161013957565b600435906001600160a01b038216820361013957565b604081019081106001600160401b03821117610ecd57604052565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b03821117610ecd57604052565b6001600160401b038111610ecd57601f01601f191660200190565b6001600160401b038111610ecd5760051b60200190565b35906001600160f01b03198216820361013957565b35906001600160e01b03198216820361013957565b35906001600160801b03198216820361013957565b903561017e1982360301811215610139570190565b9035601e19823603018112156101395701602081359101916001600160401b03821161013957813603831361013957565b908060209392818452848401375f828201840152601f01601f1916010190565b359061ffff8216820361013957565b6001600160801b0319610ffa82610f5e565b1682526001600160e01b031961101260208301610f49565b16602083015260408101359163ffffffff198316809303610139576110fe9260408201526001600160801b031961104b60608401610f5e565b1660608201526080820135608082015260a082013560a082015260c082013560c08201526110ef6110e361109861108560e0860186610f88565b61018060e0870152610180860191610fb9565b61ffff6110a86101008701610fd9565b1661010085015261ffff6110bf6101208701610fd9565b166101208501526110d4610140860186610f88565b90858303610140870152610fb9565b92610160810190610f88565b91610160818503910152610fb9565b90565b9035605e1982360301811215610139570190565b8051156111225760200190565b634e487b7160e01b5f52603260045260245ffd5b80518210156111225760209160051b010190565b5f546001600160a01b0316330361115d57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fdfea264697066735822122034bc1676d3fc5f4f1992955e2c63c1e6992e5b674ecb340d7030d9c9516267f664736f6c634300081e00330000000000000000000000000000000000000000000000000000000000028c590000000000000000000000004779d18931b35540f84b0cd0e9633855b84df7b800000000000000000000000018a235e18bee9cda516f227aa97ae6627e7d612c
Deployed ByteCode
0x6080806040526004361015610012575f80fd5b5f3560e01c90816314bcf3dd14610d4b575080631610729014610af157806336383dc714610aad5780634ef36a56146109f7578063715018a61461099457806379ba5097146108cb5780638da5cb5b146108a45780639d7809b514610867578063a2f7b3a514610825578063a5a1d0c5146107e2578063a91951a2146101ba578063b51ec328146101a0578063d632cf3514610182578063e30c39781461015a578063ee45abb01461013d5763f2fde38b146100cc575f80fd5b34610139576020366003190112610139576100e5610e9c565b6100ed61114a565b60018060a01b0316806001600160601b0360a01b600154161760015560018060a01b035f54167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b5f80fd5b34610139575f366003190112610139576020600254604051908152f35b34610139575f366003190112610139576001546040516001600160a01b039091168152602090f35b34610139575f3660031901126101395760206040516301e133808152f35b34610139575f3660031901126101395760206040515f8152f35b34610139576020366003190112610139576004356001600160401b0381116101395780600401908036036101206003198201126101395760405163089a168f60e01b8152602060048201526001600160f01b031961021785610f34565b16602482015261ffff60f01b61022f60248501610f34565b16604482015263ffffffff60e01b61024960448501610f49565b16606482015261ffff60f01b61026160648501610f34565b16608482015261ffff60f01b61027960848501610f34565b1660a48201526001600160801b031961029460a48501610f5e565b1660c482015260c48301356001600160601b031981168091036101395760e48201526102db6102c760e485018096610f73565b610120610104840152610144830190610fe8565b61010484013560c2198401811215610139578282036023190161012484015284016004810161037461035961033f6103246103168580610f88565b60c0895260c0890191610fb9565b6103316024870186610f88565b9088830360208a0152610fb9565b61034c6044860185610f73565b8682036040880152610fe8565b6103666064850184610f88565b908683036060880152610fb9565b608483013591906042193685900301831215610139576103cf60a49160406103bf6004886103d798010189840360808b015261ffff6103b282610fd9565b1684526020810190610f88565b9190928160208201520191610fb9565b930190611101565b9160a0818303910152606081019161ffff6103f182610fd9565b16825260208101359063ffffffff82168092036101395761041f908392602087969501526040810190611101565b91606060408301529060c081019280925f915b600383106107a857505050505090805f9203818360018060a01b037f00000000000000000000000018a235e18bee9cda516f227aa97ae6627e7d612c165af190811561079d575f91610718575b5015610709576040918251936104958486610ee1565b60018552601f198401366020870137359161018219018212156101395701610164810135602219368390030181121561013957016004018035906001600160401b0382116101395760200181360381136101395735906001600160601b0319821691601482106106e4575b505060601c61050e83611115565b52815161051a81610f1d565b9061052783519283610ee1565b808252601f1961053682610f1d565b013660208401376001600160401b034216806001600160401b0381116106b257505f5b8281106105745760208561056c86611115565b519051908152f35b6001600160a01b036105868288611136565b51165f52600460205260ff855f2054166106d5576001600160a01b036105ac8288611136565b51165f9081526004602052859020805460ff191660011790556001600160a01b036105d78288611136565b5116156106c6576001600160a01b036105f08288611136565b51168551906105fe82610eb2565b81526020808201848152600280545f9081526003909352918890209251835491516001600160e01b03199092166001600160a01b03919091161760a09190911b67ffffffffffffffff60a01b161790915554908161065c8287611136565b525f6001600160a01b03610670838a611136565b5116837fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb60208a51888152a45f1982146106b257600180920160025501610559565b634e487b7160e01b5f52601160045260245ffd5b630c3bd7cd60e11b5f5260045ffd5b63a239527960e01b5f5260045ffd5b6bffffffffffffffffffffffff1960149290920360031b82901b161690508380610500565b631cbfe78f60e21b5f5260045ffd5b90503d805f833e6107298183610ee1565b8101604082820312610139578151918215158303610139576020810151906001600160401b038211610139570181601f8201121561013957805161076c81610f02565b9261077a6040519485610ee1565b81845260208284010111610139575f928160208094018483015e0101528461047f565b6040513d5f823e3d90fd5b9193955091936020806107d0600193605f198982030187526107ca8a87610f88565b90610fb9565b97019301930190928695949293610432565b34610139575f3660031901126101395760206040516001600160401b037f0000000000000000000000000000000000000000000000000000000000028c59168152f35b34610139576020366003190112610139576004355f5260036020526040805f20546001600160401b0382519160018060a01b038116835260a01c166020820152f35b34610139576020366003190112610139576001600160a01b03610888610e9c565b165f526004602052602060ff60405f2054166040519015158152f35b34610139575f366003190112610139575f546040516001600160a01b039091168152602090f35b34610139575f36600319011261013957600154336001600160a01b039091160361093d57600180546001600160a01b03199081169091555f805433928116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b34610139575f366003190112610139576109ac61114a565b600180546001600160a01b03199081169091555f80549182168155906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610139576020366003190112610139576004356001600160401b03811161013957610a27903690600401610e6c565b90610a3061114a565b5f5b82811015610aab578060051b82013590815f52600360205260018060a01b0360405f205416156106c657816001925f526003602052828060a01b0360405f205416817f89d0dca869ffe08b709ca9ff5adfd5ee8d9de2750d0561e15df614c7a2596d8e5f80a35f5260036020525f604081205501610a32565b005b34610139575f366003190112610139576040517f00000000000000000000000018a235e18bee9cda516f227aa97ae6627e7d612c6001600160a01b03168152602090f35b34610139576020366003190112610139576004356001600160401b03811161013957610b21903690600401610e6c565b610b2961114a565b610b3281610f1d565b91610b406040519384610ee1565b818352602083019160051b81019036821161013957915b818310610d2b57835184610b6a82610f1d565b91610b786040519384610ee1565b808352610b8481610f1d565b602084019290601f19013684376001600160401b0342165f5b838110610be8578486604051918291602083019060208452518091526040830191905f5b818110610bcf575050500390f35b8251845285945060209384019390920191600101610bc1565b6001600160a01b03610bfa8285611136565b51165f52600460205260ff60405f2054166106d5576001600160a01b03610c218285611136565b51165f908152600460205260409020805460ff191660011790556001600160a01b03610c4d8285611136565b5116156106c6576001600160a01b03610c668285611136565b511660405190610c7582610eb2565b81526020808201848152600280545f908152600390935260409092209251835491516001600160e01b03199092166001600160a01b03919091161760a09190911b67ffffffffffffffff60a01b1617909155549081610cd48289611136565b525f6001600160a01b03610ce88387611136565b5116837fbbe529d240965181270c1e2e32a80761e8807dda1ee9765e326178bd6804a9cb6020604051888152a45f1982146106b257600180920160025501610b9d565b82356001600160a01b038116810361013957815260209283019201610b57565b3461013957606036600319011261013957602435906044356001600160401b0381116101395736602382011215610139578060040135906001600160401b0382116101395736602483830101116101395760598203610e5d57816004116101395781601811610139576028810135928415610e4e5760806008945f966b2b22a924a32cafa82927a7a360a11b84526001600160401b037f0000000000000000000000000000000000000000000000000000000000028c59166020850152306040850152606084015260018060a01b039060601c169101526017198201603c610e3282610f02565b92610e406040519485610ee1565b828452016020830137010152005b6318e48a7560e21b5f5260045ffd5b637bb2c12960e01b5f5260045ffd5b9181601f84011215610139578235916001600160401b038311610139576020808501948460051b01011161013957565b600435906001600160a01b038216820361013957565b604081019081106001600160401b03821117610ecd57604052565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b03821117610ecd57604052565b6001600160401b038111610ecd57601f01601f191660200190565b6001600160401b038111610ecd5760051b60200190565b35906001600160f01b03198216820361013957565b35906001600160e01b03198216820361013957565b35906001600160801b03198216820361013957565b903561017e1982360301811215610139570190565b9035601e19823603018112156101395701602081359101916001600160401b03821161013957813603831361013957565b908060209392818452848401375f828201840152601f01601f1916010190565b359061ffff8216820361013957565b6001600160801b0319610ffa82610f5e565b1682526001600160e01b031961101260208301610f49565b16602083015260408101359163ffffffff198316809303610139576110fe9260408201526001600160801b031961104b60608401610f5e565b1660608201526080820135608082015260a082013560a082015260c082013560c08201526110ef6110e361109861108560e0860186610f88565b61018060e0870152610180860191610fb9565b61ffff6110a86101008701610fd9565b1661010085015261ffff6110bf6101208701610fd9565b166101208501526110d4610140860186610f88565b90858303610140870152610fb9565b92610160810190610f88565b91610160818503910152610fb9565b90565b9035605e1982360301811215610139570190565b8051156111225760200190565b634e487b7160e01b5f52603260045260245ffd5b80518210156111225760209160051b010190565b5f546001600160a01b0316330361115d57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fdfea264697066735822122034bc1676d3fc5f4f1992955e2c63c1e6992e5b674ecb340d7030d9c9516267f664736f6c634300081e0033
External libraries
LibForcedInclusion : 0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14
LibInboxSetup : 0xf88Ef5437749A225621101BE8C1BE1A0cE967758