Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
BunnyInbox
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import {IEigenDACertVerifierBase} from "src/integrations/cert/interfaces/IEigenDACertVerifierBase.sol";
import {EigenDACertTypes as CT} from "src/integrations/cert/EigenDACertTypes.sol";
import {EigenDATypesV1 as DATypesV1} from "src/core/libraries/v1/EigenDATypesV1.sol";
import {EigenDATypesV2 as DATypesV2} from "src/core/libraries/v2/EigenDATypesV2.sol";
import {BN254} from "lib/eigenlayer-middleware/src/libraries/BN254.sol";
import {RLPReader} from "src/integrations/cert/libraries/RLPReader.sol";
/// @title BunnyInbox
/// @notice Implementation contract for RLP DA cert decoding, deployed behind a TransparentUpgradeableProxy
/// @dev Uses storage variable instead of immutable for verifier to support proxy pattern.
/// Accepts raw DA cert calldata via fallback() in format: 4-byte prefix + RLP-encoded EigenDACertV3
/// Prefix format: [0x01 op_version][0x01 generic_mode][0x00 da_layer][0x02 cert_version]
contract BunnyInbox is Initializable {
using RLPReader for bytes;
using RLPReader for RLPReader.RLPItem;
/// @notice The underlying cert verifier that will validate the decoded certificate
IEigenDACertVerifierBase public verifier;
/// @notice Length of the prefix to strip from raw calldata
uint256 public constant PREFIX_LENGTH = 4;
error InvalidRawCertLength();
error RLPDecodingFailed();
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/// @notice Initializes the contract with the verifier address
/// @param _verifier Address of the EigenDACertVerifier contract
function initialize(IEigenDACertVerifierBase _verifier) external initializer {
verifier = _verifier;
}
/// @notice Fallback function that verifies raw DA certificate from msg.data
/// @dev Processes msg.data directly: 4-byte prefix + RLP-encoded EigenDACertV3
/// Reverts if the certificate is invalid
fallback() external {
if (msg.data.length <= PREFIX_LENGTH) {
revert InvalidRawCertLength();
}
// Strip the 4-byte prefix
bytes memory rlpCert = msg.data[PREFIX_LENGTH:];
// Decode the RLP data into EigenDACertV3 struct
CT.EigenDACertV3 memory cert = _rlpDecodeCert(rlpCert);
// Call the verifier with struct directly (reverts on invalid cert)
verifier.checkDACertReverts(cert);
}
/// @notice Decodes RLP-encoded data into an EigenDACertV3 struct
/// @param rlpData RLP-encoded certificate data
/// @return cert The decoded EigenDACertV3 struct
function _rlpDecodeCert(bytes memory rlpData) internal pure returns (CT.EigenDACertV3 memory cert) {
// Top-level is a list of 4 items:
// [batchHeader, blobInclusionInfo, nonSignerStakesAndSignature, signedQuorumNumbers]
RLPReader.RLPItem[] memory items = rlpData.toRlpItem().toList();
cert.batchHeader = _decodeBatchHeaderV2(items[0]);
cert.blobInclusionInfo = _decodeBlobInclusionInfo(items[1]);
cert.nonSignerStakesAndSignature = _decodeNonSignerStakesAndSignature(items[2]);
cert.signedQuorumNumbers = items[3].toBytes();
}
/// @notice Decodes BatchHeaderV2 from RLP
function _decodeBatchHeaderV2(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV2.BatchHeaderV2 memory header)
{
RLPReader.RLPItem[] memory fields = item.toList();
header.batchRoot = fields[0].toBytes32();
header.referenceBlockNumber = fields[1].toUint32();
}
/// @notice Decodes BlobInclusionInfo from RLP
function _decodeBlobInclusionInfo(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV2.BlobInclusionInfo memory info)
{
RLPReader.RLPItem[] memory fields = item.toList();
info.blobCertificate = _decodeBlobCertificate(fields[0]);
info.blobIndex = fields[1].toUint32();
info.inclusionProof = fields[2].toBytes();
}
/// @notice Decodes BlobCertificate from RLP
function _decodeBlobCertificate(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV2.BlobCertificate memory cert)
{
RLPReader.RLPItem[] memory fields = item.toList();
cert.blobHeader = _decodeBlobHeaderV2(fields[0]);
cert.signature = fields[1].toBytes();
cert.relayKeys = _decodeUint32Array(fields[2]);
}
/// @notice Decodes BlobHeaderV2 from RLP
function _decodeBlobHeaderV2(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV2.BlobHeaderV2 memory header)
{
RLPReader.RLPItem[] memory fields = item.toList();
header.version = fields[0].toUint16();
header.quorumNumbers = fields[1].toBytes();
header.commitment = _decodeBlobCommitment(fields[2]);
header.paymentHeaderHash = fields[3].toBytes32();
}
/// @notice Decodes BlobCommitment from RLP
function _decodeBlobCommitment(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV2.BlobCommitment memory commitment)
{
RLPReader.RLPItem[] memory fields = item.toList();
commitment.commitment = _decodeG1Point(fields[0]);
commitment.lengthCommitment = _decodeG2Point(fields[1]);
commitment.lengthProof = _decodeG2Point(fields[2]);
commitment.length = fields[3].toUint32();
}
/// @notice Decodes NonSignerStakesAndSignature from RLP
function _decodeNonSignerStakesAndSignature(RLPReader.RLPItem memory item)
internal
pure
returns (DATypesV1.NonSignerStakesAndSignature memory sig)
{
RLPReader.RLPItem[] memory fields = item.toList();
sig.nonSignerQuorumBitmapIndices = _decodeUint32Array(fields[0]);
sig.nonSignerPubkeys = _decodeG1PointArray(fields[1]);
sig.quorumApks = _decodeG1PointArray(fields[2]);
sig.apkG2 = _decodeG2Point(fields[3]);
sig.sigma = _decodeG1Point(fields[4]);
sig.quorumApkIndices = _decodeUint32Array(fields[5]);
sig.totalStakeIndices = _decodeUint32Array(fields[6]);
sig.nonSignerStakeIndices = _decodeUint32ArrayArray(fields[7]);
}
/// @notice Decodes a G1Point from RLP (2-element list: X, Y)
function _decodeG1Point(RLPReader.RLPItem memory item) internal pure returns (BN254.G1Point memory point) {
RLPReader.RLPItem[] memory fields = item.toList();
point.X = fields[0].toUint256();
point.Y = fields[1].toUint256();
}
/// @notice Decodes a G2Point from RLP (2-element list: X[2], Y[2])
function _decodeG2Point(RLPReader.RLPItem memory item) internal pure returns (BN254.G2Point memory point) {
RLPReader.RLPItem[] memory fields = item.toList();
// X and Y are each 2-element arrays
RLPReader.RLPItem[] memory xFields = fields[0].toList();
RLPReader.RLPItem[] memory yFields = fields[1].toList();
point.X[0] = xFields[0].toUint256();
point.X[1] = xFields[1].toUint256();
point.Y[0] = yFields[0].toUint256();
point.Y[1] = yFields[1].toUint256();
}
/// @notice Decodes an array of G1Points from RLP
function _decodeG1PointArray(RLPReader.RLPItem memory item)
internal
pure
returns (BN254.G1Point[] memory points)
{
RLPReader.RLPItem[] memory list = item.toList();
points = new BN254.G1Point[](list.length);
for (uint256 i = 0; i < list.length; i++) {
points[i] = _decodeG1Point(list[i]);
}
}
/// @notice Decodes an array of uint32 from RLP
function _decodeUint32Array(RLPReader.RLPItem memory item) internal pure returns (uint32[] memory arr) {
RLPReader.RLPItem[] memory list = item.toList();
arr = new uint32[](list.length);
for (uint256 i = 0; i < list.length; i++) {
arr[i] = list[i].toUint32();
}
}
/// @notice Decodes a 2D array of uint32 from RLP
function _decodeUint32ArrayArray(RLPReader.RLPItem memory item) internal pure returns (uint32[][] memory arr) {
RLPReader.RLPItem[] memory list = item.toList();
arr = new uint32[][](list.length);
for (uint256 i = 0; i < list.length; i++) {
arr[i] = _decodeUint32Array(list[i]);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {EigenDACertTypes as CT} from "src/integrations/cert/EigenDACertTypes.sol";
interface IEigenDACertVerifierBase {
/// @notice Check a DA cert's validity
/// @param abiEncodedCert The ABI encoded certificate. Any cert verifier should decode this ABI encoding based on the certificate version.
/// @return status An enum value. Success is always mapped to 1, and other values are errors specific to each CertVerifier.
/// @dev This function should never revert on invalid certs, and should instead return an error status code.
/// This is because cert invalidity needs to be proven to the rollup's derivation pipeline that the cert can be discarded.
/// We use Risc0's Steel library for this purpose, which doesn't support reverts: https://github.com/risc0/risc0-ethereum/issues/438
function checkDACert(bytes calldata abiEncodedCert) external view returns (uint8 status);
/// @notice Check a DA cert's validity, reverts on invalid certs
/// @param daCert The EigenDACertV3 struct to verify
/// @dev This function reverts on invalid certs instead of returning an error status code
function checkDACertReverts(CT.EigenDACertV3 calldata daCert) external view;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {EigenDATypesV1 as DATypesV1} from "src/core/libraries/v1/EigenDATypesV1.sol";
import {EigenDATypesV2 as DATypesV2} from "src/core/libraries/v2/EigenDATypesV2.sol";
/// @title EigenDACertTypes
/// @notice This library defines the types for each EigenDA certificate version.
/// @dev It is required that RBN be located in positions 32:64 (padded) in the ABI encoded certificate.
library EigenDACertTypes {
struct EigenDACertV3 {
DATypesV2.BatchHeaderV2 batchHeader;
DATypesV2.BlobInclusionInfo blobInclusionInfo;
DATypesV1.NonSignerStakesAndSignature nonSignerStakesAndSignature;
bytes signedQuorumNumbers;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {BN254} from "lib/eigenlayer-middleware/src/libraries/BN254.sol";
library EigenDATypesV1 {
struct VersionedBlobParams {
uint32 maxNumOperators;
uint32 numChunks;
uint8 codingRate;
}
struct SecurityThresholds {
uint8 confirmationThreshold;
uint8 adversaryThreshold;
}
struct QuorumBlobParam {
uint8 quorumNumber;
uint8 adversaryThresholdPercentage;
uint8 confirmationThresholdPercentage;
uint32 chunkLength;
}
struct BlobHeader {
BN254.G1Point commitment;
uint32 dataLength;
QuorumBlobParam[] quorumBlobParams;
}
struct ReducedBatchHeader {
bytes32 blobHeadersRoot;
uint32 referenceBlockNumber;
}
struct BatchHeader {
bytes32 blobHeadersRoot;
bytes quorumNumbers;
bytes signedStakeForQuorums;
uint32 referenceBlockNumber;
}
struct BatchMetadata {
BatchHeader batchHeader;
bytes32 signatoryRecordHash;
uint32 confirmationBlockNumber;
}
struct BlobVerificationProof {
uint32 batchId;
uint32 blobIndex;
BatchMetadata batchMetadata;
bytes inclusionProof;
bytes quorumIndices;
}
struct NonSignerStakesAndSignature {
uint32[] nonSignerQuorumBitmapIndices;
BN254.G1Point[] nonSignerPubkeys;
BN254.G1Point[] quorumApks;
BN254.G2Point apkG2;
BN254.G1Point sigma;
uint32[] quorumApkIndices;
uint32[] totalStakeIndices;
uint32[][] nonSignerStakeIndices;
}
struct QuorumStakeTotals {
uint96[] signedStakeForQuorum;
uint96[] totalStakeForQuorum;
}
struct CheckSignaturesIndices {
uint32[] nonSignerQuorumBitmapIndices;
uint32[] quorumApkIndices;
uint32[] totalStakeIndices;
uint32[][] nonSignerStakeIndices;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {BN254} from "lib/eigenlayer-middleware/src/libraries/BN254.sol";
library EigenDATypesV2 {
struct RelayInfo {
address relayAddress;
string relayURL;
}
struct DisperserInfo {
address disperserAddress;
}
struct BlobInclusionInfo {
BlobCertificate blobCertificate;
uint32 blobIndex;
bytes inclusionProof;
}
struct BlobCertificate {
BlobHeaderV2 blobHeader;
bytes signature;
uint32[] relayKeys;
}
struct BlobHeaderV2 {
uint16 version;
bytes quorumNumbers;
BlobCommitment commitment;
bytes32 paymentHeaderHash;
}
struct BlobCommitment {
BN254.G1Point commitment;
BN254.G2Point lengthCommitment;
BN254.G2Point lengthProof;
uint32 length;
}
struct SignedBatch {
BatchHeaderV2 batchHeader;
Attestation attestation;
}
struct BatchHeaderV2 {
bytes32 batchRoot;
uint32 referenceBlockNumber;
}
struct Attestation {
BN254.G1Point[] nonSignerPubkeys;
BN254.G1Point[] quorumApks;
BN254.G1Point sigma;
BN254.G2Point apkG2;
uint32[] quorumNumbers;
}
}// SPDX-License-Identifier: MIT
// several functions are taken or adapted from https://github.com/HarryR/solcrypto/blob/master/contracts/altbn128.sol (MIT license):
// Copyright 2017 Christian Reitwiessner
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// The remainder of the code in this library is written by LayrLabs Inc. and is also under an MIT license
pragma solidity ^0.8.12;
/**
* @title Library for operations on the BN254 elliptic curve.
* @author Layr Labs, Inc.
* @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
* @notice Contains BN254 parameters, common operations (addition, scalar mul, pairing), and BLS signature functionality.
*/
library BN254 {
// modulus for the underlying field F_p of the elliptic curve
uint256 internal constant FP_MODULUS =
21888242871839275222246405745257275088696311157297823662689037894645226208583;
// modulus for the underlying field F_r of the elliptic curve
uint256 internal constant FR_MODULUS =
21888242871839275222246405745257275088548364400416034343698204186575808495617;
struct G1Point {
uint256 X;
uint256 Y;
}
// Encoding of field elements is: X[1] * i + X[0]
struct G2Point {
uint256[2] X;
uint256[2] Y;
}
function generatorG1() internal pure returns (G1Point memory) {
return G1Point(1, 2);
}
// generator of group G2
/// @dev Generator point in F_q2 is of the form: (x0 + ix1, y0 + iy1).
uint256 internal constant G2x1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 internal constant G2x0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 internal constant G2y1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 internal constant G2y0 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
/// @notice returns the G2 generator
/// @dev mind the ordering of the 1s and 0s!
/// this is because of the (unknown to us) convention used in the bn254 pairing precompile contract
/// "Elements a * i + b of F_p^2 are encoded as two elements of F_p, (a, b)."
/// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md#encoding
function generatorG2() internal pure returns (G2Point memory) {
return G2Point([G2x1, G2x0], [G2y1, G2y0]);
}
// negation of the generator of group G2
/// @dev Generator point in F_q2 is of the form: (x0 + ix1, y0 + iy1).
uint256 internal constant nG2x1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 internal constant nG2x0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 internal constant nG2y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052;
uint256 internal constant nG2y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653;
function negGeneratorG2() internal pure returns (G2Point memory) {
return G2Point([nG2x1, nG2x0], [nG2y1, nG2y0]);
}
bytes32 internal constant powersOfTauMerkleRoot =
0x22c998e49752bbb1918ba87d6d59dd0e83620a311ba91dd4b2cc84990b31b56f;
/**
* @param p Some point in G1.
* @return The negation of `p`, i.e. p.plus(p.negate()) should be zero.
*/
function negate(G1Point memory p) internal pure returns (G1Point memory) {
// The prime q in the base field F_q for G1
if (p.X == 0 && p.Y == 0) {
return G1Point(0, 0);
} else {
return G1Point(p.X, FP_MODULUS - (p.Y % FP_MODULUS));
}
}
/**
* @return r the sum of two points of G1
*/
function plus(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
uint256[4] memory input;
input[0] = p1.X;
input[1] = p1.Y;
input[2] = p2.X;
input[3] = p2.Y;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 6, input, 0x80, r, 0x40)
// Use "invalid" to make gas estimation work
switch success
case 0 {
invalid()
}
}
require(success, "ec-add-failed");
}
/**
* @notice an optimized ecMul implementation that takes O(log_2(s)) ecAdds
* @param p the point to multiply
* @param s the scalar to multiply by
* @dev this function is only safe to use if the scalar is 9 bits or less
*/
function scalar_mul_tiny(BN254.G1Point memory p, uint16 s) internal view returns (BN254.G1Point memory) {
require(s < 2**9, "scalar-too-large");
// if s is 1 return p
if(s == 1) {
return p;
}
// the accumulated product to return
BN254.G1Point memory acc = BN254.G1Point(0, 0);
// the 2^n*p to add to the accumulated product in each iteration
BN254.G1Point memory p2n = p;
// value of most significant bit
uint16 m = 1;
// index of most significant bit
uint8 i = 0;
//loop until we reach the most significant bit
while(s >= m){
unchecked {
// if the current bit is 1, add the 2^n*p to the accumulated product
if ((s >> i) & 1 == 1) {
acc = plus(acc, p2n);
}
// double the 2^n*p for the next iteration
p2n = plus(p2n, p2n);
// increment the index and double the value of the most significant bit
m <<= 1;
++i;
}
}
// return the accumulated product
return acc;
}
/**
* @return r the product of a point on G1 and a scalar, i.e.
* p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all
* points p.
*/
function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) {
uint256[3] memory input;
input[0] = p.X;
input[1] = p.Y;
input[2] = s;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 7, input, 0x60, r, 0x40)
// Use "invalid" to make gas estimation work
switch success
case 0 {
invalid()
}
}
require(success, "ec-mul-failed");
}
/**
* @return The result of computing the pairing check
* e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
* For example,
* pairing([P1(), P1().negate()], [P2(), P2()]) should return true.
*/
function pairing(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2
) internal view returns (bool) {
G1Point[2] memory p1 = [a1, b1];
G2Point[2] memory p2 = [a2, b2];
uint256[12] memory input;
for (uint256 i = 0; i < 2; i++) {
uint256 j = i * 6;
input[j + 0] = p1[i].X;
input[j + 1] = p1[i].Y;
input[j + 2] = p2[i].X[0];
input[j + 3] = p2[i].X[1];
input[j + 4] = p2[i].Y[0];
input[j + 5] = p2[i].Y[1];
}
uint256[1] memory out;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 8, input, mul(12, 0x20), out, 0x20)
// Use "invalid" to make gas estimation work
switch success
case 0 {
invalid()
}
}
require(success, "pairing-opcode-failed");
return out[0] != 0;
}
/**
* @notice This function is functionally the same as pairing(), however it specifies a gas limit
* the user can set, as a precompile may use the entire gas budget if it reverts.
*/
function safePairing(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2,
uint256 pairingGas
) internal view returns (bool, bool) {
G1Point[2] memory p1 = [a1, b1];
G2Point[2] memory p2 = [a2, b2];
uint256[12] memory input;
for (uint256 i = 0; i < 2; i++) {
uint256 j = i * 6;
input[j + 0] = p1[i].X;
input[j + 1] = p1[i].Y;
input[j + 2] = p2[i].X[0];
input[j + 3] = p2[i].X[1];
input[j + 4] = p2[i].Y[0];
input[j + 5] = p2[i].Y[1];
}
uint256[1] memory out;
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(pairingGas, 8, input, mul(12, 0x20), out, 0x20)
}
//Out is the output of the pairing precompile, either 0 or 1 based on whether the two pairings are equal.
//Success is true if the precompile actually goes through (aka all inputs are valid)
return (success, out[0] != 0);
}
/// @return hashedG1 the keccak256 hash of the G1 Point
/// @dev used for BLS signatures
function hashG1Point(BN254.G1Point memory pk) internal pure returns (bytes32 hashedG1) {
assembly {
mstore(0, mload(pk))
mstore(0x20, mload(add(0x20, pk)))
hashedG1 := keccak256(0, 0x40)
}
}
/// @return the keccak256 hash of the G2 Point
/// @dev used for BLS signatures
function hashG2Point(
BN254.G2Point memory pk
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(pk.X[0], pk.X[1], pk.Y[0], pk.Y[1]));
}
/**
* @notice adapted from https://github.com/HarryR/solcrypto/blob/master/contracts/altbn128.sol
*/
function hashToG1(bytes32 _x) internal view returns (G1Point memory) {
uint256 beta = 0;
uint256 y = 0;
uint256 x = uint256(_x) % FP_MODULUS;
while (true) {
(beta, y) = findYFromX(x);
// y^2 == beta
if( beta == mulmod(y, y, FP_MODULUS) ) {
return G1Point(x, y);
}
x = addmod(x, 1, FP_MODULUS);
}
return G1Point(0, 0);
}
/**
* Given X, find Y
*
* where y = sqrt(x^3 + b)
*
* Returns: (x^3 + b), y
*/
function findYFromX(uint256 x) internal view returns (uint256, uint256) {
// beta = (x^3 + b) % p
uint256 beta = addmod(mulmod(mulmod(x, x, FP_MODULUS), x, FP_MODULUS), 3, FP_MODULUS);
// y^2 = x^3 + b
// this acts like: y = sqrt(beta) = beta^((p+1) / 4)
uint256 y = expMod(beta, 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52, FP_MODULUS);
return (beta, y);
}
function expMod(uint256 _base, uint256 _exponent, uint256 _modulus) internal view returns (uint256 retval) {
bool success;
uint256[1] memory output;
uint[6] memory input;
input[0] = 0x20; // baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
input[1] = 0x20; // expLen = new(big.Int).SetBytes(getData(input, 32, 32))
input[2] = 0x20; // modLen = new(big.Int).SetBytes(getData(input, 64, 32))
input[3] = _base;
input[4] = _exponent;
input[5] = _modulus;
assembly {
success := staticcall(sub(gas(), 2000), 5, input, 0xc0, output, 0x20)
// Use "invalid" to make gas estimation work
switch success
case 0 {
invalid()
}
}
require(success, "BN254.expMod: call failure");
return output[0];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/// @title RLPReader
/// @notice Library for parsing RLP-encoded data
/// @dev Based on https://github.com/hamdiallam/Solidity-RLP (Apache 2.0)
library RLPReader {
uint8 internal constant STRING_SHORT_START = 0x80;
uint8 internal constant STRING_LONG_START = 0xb8;
uint8 internal constant LIST_SHORT_START = 0xc0;
uint8 internal constant LIST_LONG_START = 0xf8;
uint8 internal constant WORD_SIZE = 32;
error InvalidRLPData();
error InvalidRLPList();
error InvalidRLPString();
struct RLPItem {
uint256 len;
uint256 memPtr;
}
/// @notice Converts bytes to an RLPItem
/// @param item RLP-encoded bytes
/// @return RLPItem pointing to the data
function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
uint256 memPtr;
assembly {
memPtr := add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/// @notice Get the list of items from an RLP-encoded list
/// @param item RLPItem representing an RLP list
/// @return result Array of RLPItems
function toList(RLPItem memory item) internal pure returns (RLPItem[] memory result) {
if (!isList(item)) {
revert InvalidRLPList();
}
uint256 items = numItems(item);
result = new RLPItem[](items);
uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 dataLen;
for (uint256 i = 0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
}
/// @notice Check if the RLPItem is a list
/// @param item RLPItem
/// @return True if the item is a list, false otherwise
function isList(RLPItem memory item) internal pure returns (bool) {
if (item.len == 0) return false;
uint8 byte0;
uint256 memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
}
return byte0 >= LIST_SHORT_START;
}
/// @notice Number of items in an RLP-encoded list
/// @param item RLPItem
/// @return Number of items in the list
function numItems(RLPItem memory item) internal pure returns (uint256) {
if (item.len == 0) return 0;
uint256 count = 0;
uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr);
count++;
}
return count;
}
/// @notice Decode an RLPItem into bytes
/// @param item RLPItem
/// @return Decoded bytes
function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
if (item.len == 0) {
revert InvalidRLPString();
}
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
bytes memory result = new bytes(len);
uint256 destPtr;
assembly {
destPtr := add(result, 0x20)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/// @notice Decode an RLPItem into a uint
/// @param item RLPItem
/// @return Decoded uint
function toUint(RLPItem memory item) internal pure returns (uint256) {
if (item.len == 0 || item.len > 33) {
revert InvalidRLPData();
}
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
uint256 result;
uint256 memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
// Shift to the correct position if len < 32 bytes
if lt(len, 32) { result := div(result, exp(256, sub(32, len))) }
}
return result;
}
/// @notice Decode an RLPItem into a uint8
/// @param item RLPItem
/// @return Decoded uint8
function toUint8(RLPItem memory item) internal pure returns (uint8) {
return uint8(toUint(item));
}
/// @notice Decode an RLPItem into a uint16
/// @param item RLPItem
/// @return Decoded uint16
function toUint16(RLPItem memory item) internal pure returns (uint16) {
return uint16(toUint(item));
}
/// @notice Decode an RLPItem into a uint32
/// @param item RLPItem
/// @return Decoded uint32
function toUint32(RLPItem memory item) internal pure returns (uint32) {
return uint32(toUint(item));
}
/// @notice Decode an RLPItem into a uint256
/// @param item RLPItem
/// @return Decoded uint256
function toUint256(RLPItem memory item) internal pure returns (uint256) {
return toUint(item);
}
/// @notice Decode an RLPItem into bytes32
/// @param item RLPItem
/// @return Decoded bytes32
function toBytes32(RLPItem memory item) internal pure returns (bytes32) {
// Special handling for bytes32: check that the length is exactly 32 bytes
if (item.len == 0) {
revert InvalidRLPData();
}
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
if (len != 32) {
revert InvalidRLPData();
}
bytes32 result;
uint256 memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
}
return result;
}
/// @notice Get the payload offset (skip the RLP header)
/// @param memPtr Pointer to the start of the RLP item
/// @return Offset to the payload
function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
uint8 byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) {
return 0;
} else if (byte0 < STRING_LONG_START) {
return 1;
} else if (byte0 < LIST_SHORT_START) {
return byte0 - (STRING_LONG_START - 1) + 1;
} else if (byte0 < LIST_LONG_START) {
return 1;
} else {
return byte0 - (LIST_LONG_START - 1) + 1;
}
}
/// @notice Get the full length of an RLP item including header
/// @param memPtr Pointer to the start of the RLP item
/// @return Length of the item including header
function _itemLength(uint256 memPtr) private pure returns (uint256) {
uint256 itemLen;
uint8 byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) {
itemLen = 1;
} else if (byte0 < STRING_LONG_START) {
itemLen = byte0 - STRING_SHORT_START + 1;
} else if (byte0 < LIST_SHORT_START) {
uint256 lenOfStrLen = byte0 - (STRING_LONG_START - 1);
uint256 strLen;
assembly {
let lenPtr := add(1, memPtr)
strLen := div(mload(lenPtr), exp(256, sub(32, lenOfStrLen)))
}
itemLen = 1 + lenOfStrLen + strLen;
} else if (byte0 < LIST_LONG_START) {
itemLen = byte0 - LIST_SHORT_START + 1;
} else {
uint256 lenOfListLen = byte0 - (LIST_LONG_START - 1);
uint256 listLen;
assembly {
let lenPtr := add(1, memPtr)
listLen := div(mload(lenPtr), exp(256, sub(32, lenOfListLen)))
}
itemLen = 1 + lenOfListLen + listLen;
}
return itemLen;
}
/// @notice Copy memory from source to destination
/// @param src Source pointer
/// @param dest Destination pointer
/// @param len Length to copy
function copy(uint256 src, uint256 dest, uint256 len) private pure {
if (len == 0) return;
// Copy word-length chunks
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
if (len > 0) {
// Copy remaining bytes
uint256 mask = 256 ** (WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}{
"remappings": [
"@openzeppelin/=node_modules/@openzeppelin/",
"@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/",
"@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/",
"@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/",
"ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/",
"eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/",
"eigenlayer-middleware/=lib/eigenlayer-middleware/",
"erc4626-tests/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/contracts/",
"zeus-templates/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/zeus-templates/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false
}Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidRLPData","type":"error"},{"inputs":[],"name":"InvalidRLPList","type":"error"},{"inputs":[],"name":"InvalidRLPString","type":"error"},{"inputs":[],"name":"InvalidRawCertLength","type":"error"},{"inputs":[],"name":"RLPDecodingFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"PREFIX_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IEigenDACertVerifierBase","name":"_verifier","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract IEigenDACertVerifierBase","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611ae2806100ed6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632418833f1461015d5780632b7ac3f314610178578063c4d66de8146101c3575b6004361161007b576040517f0f601ef500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061008a36600481846113af565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394506100cc92508491506101d89050565b6000546040517f1e5de2ab00000000000000000000000000000000000000000000000000000000815291925062010000900473ffffffffffffffffffffffffffffffffffffffff1690631e5de2ab90610129908490600401611631565b60006040518083038186803b15801561014157600080fd5b505afa158015610155573d6000803e3d6000fd5b505050505050005b610165600481565b6040519081526020015b60405180910390f35b60005461019e9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016f565b6101d66101d1366004611806565b6102c9565b005b6101e0611210565b600061021b6102168460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61049d565b90506102408160008151811061023357610233611843565b60200260200101516105dc565b82528051610268908290600190811061025b5761025b611843565b6020026020010151610659565b82602001819052506102938160028151811061028657610286611843565b60200260200101516106db565b82604001819052506102be816003815181106102b1576102b1611843565b6020026020010151610821565b606083015250919050565b600054610100900460ff16158080156102e95750600054600160ff909116105b806103035750303b158015610303575060005460ff166001145b610393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff851602179055801561049957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60606104a8826108f4565b6104de576040517fc0098bd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104e983610918565b90508067ffffffffffffffff81111561050457610504611872565b60405190808252806020026020018201604052801561054957816020015b60408051808201909152600080825260208201528152602001906001900390816105225790505b509150600061055b846020015161099b565b846020015161056a91906118d0565b90506000805b838110156105d35761058183610a21565b91506040518060400160405280838152602001848152508582815181106105aa576105aa611843565b60209081029190910101526105bf82846118d0565b9250806105cb816118e8565b915050610570565b50505050919050565b604080518082019091526000808252602082015260006105fb8361049d565b90506106208160008151811061061357610613611843565b6020026020010151610b32565b82528051610648908290600190811061063b5761063b611843565b6020026020010151610bea565b63ffffffff16602083015250919050565b610661611254565b600061066c8361049d565b90506106918160008151811061068457610684611843565b6020026020010151610bfb565b825280516106ac908290600190811061063b5761063b611843565b63ffffffff16602083015280516106d090829060029081106102b1576102b1611843565b604083015250919050565b6106e361127b565b60006106ee8361049d565b90506107138160008151811061070657610706611843565b6020026020010151610c6c565b8252805161073b908290600190811061072e5761072e611843565b6020026020010151610d22565b82602001819052506107598160028151811061072e5761072e611843565b82604001819052506107848160038151811061077757610777611843565b6020026020010151610de4565b82606001819052506107af816004815181106107a2576107a2611843565b6020026020010151610eb9565b82608001819052506107cd8160058151811061070657610706611843565b8260a001819052506107eb8160068151811061070657610706611843565b8260c001819052506108168160078151811061080957610809611843565b6020026020010151610f16565b60e083015250919050565b805160609061085c576040517fa9bee26000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061086b836020015161099b565b9050600081846000015161087f9190611921565b905060008167ffffffffffffffff81111561089c5761089c611872565b6040519080825280601f01601f1916602001820160405280156108c6576020820181803683370190505b50905060006020820190506108eb8487602001516108e491906118d0565b8285610fc6565b50949350505050565b805160009061090557506000919050565b50602001515160c060009190911a101590565b805160009061092957506000919050565b600080610939846020015161099b565b846020015161094891906118d0565b905060008460000151856020015161096091906118d0565b90505b808210156109925761097482610a21565b61097e90836118d0565b91508261098a816118e8565b935050610963565b50909392505050565b8051600090811a60808110156109b45750600092915050565b60b860ff821610156109c95750600192915050565b60c060ff82161015610a00576109e1600160b8611938565b6109eb9082611938565b6109f690600161195b565b60ff169392505050565b60f860ff82161015610a155750600192915050565b6109e1600160f8611938565b80516000908190811a6080811015610a3c5760019150610b2b565b60b860ff82161015610a6857610a53608082611938565b610a5e90600161195b565b60ff169150610b2b565b60c060ff82161015610ac6576000610a82600160b8611938565b610a8c9083611938565b60ff169050600085600101826020036101000a81510491505080826001610ab391906118d0565b610abd91906118d0565b93505050610b2b565b60f860ff82161015610add57610a5360c082611938565b6000610aeb600160f8611938565b610af59083611938565b60ff169050600085600101826020036101000a81510491505080826001610b1c91906118d0565b610b2691906118d0565b935050505b5092915050565b8051600090610b6d576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b7c836020015161099b565b90506000818460000151610b909190611921565b905080602014610bcc576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080838660200151610bdf91906118d0565b519695505050505050565b6000610bf582611046565b92915050565b610c036112e1565b6000610c0e8361049d565b9050610c3381600081518110610c2657610c26611843565b60200260200101516110ea565b82528051610c4e90829060019081106102b1576102b1611843565b82602001819052506106d08160028151811061070657610706611843565b60606000610c798361049d565b9050805167ffffffffffffffff811115610c9557610c95611872565b604051908082528060200260200182016040528015610cbe578160200160208202803683370190505b50915060005b8151811015610d1b57610ce282828151811061063b5761063b611843565b838281518110610cf457610cf4611843565b63ffffffff9092166020928302919091019091015280610d13816118e8565b915050610cc4565b5050919050565b60606000610d2f8361049d565b9050805167ffffffffffffffff811115610d4b57610d4b611872565b604051908082528060200260200182016040528015610d9057816020015b6040805180820190915260008082526020820152815260200190600190039081610d695790505b50915060005b8151811015610d1b57610db48282815181106107a2576107a2611843565b838281518110610dc657610dc6611843565b60200260200101819052508080610ddc906118e8565b915050610d96565b610dec611308565b6000610df78361049d565b90506000610e1e82600081518110610e1157610e11611843565b602002602001015161049d565b90506000610e3883600181518110610e1157610e11611843565b9050610e508260008151811061063b5761063b611843565b8451528151610e6c908390600190811061063b5761063b611843565b8451602001528051610e8990829060009061063b5761063b611843565b6020850151528051610ea8908290600190811061063b5761063b611843565b602085810151015250919392505050565b60408051808201909152600080825260208201526000610ed88361049d565b9050610ef08160008151811061063b5761063b611843565b82528051610f0b908290600190811061063b5761063b611843565b602083015250919050565b60606000610f238361049d565b9050805167ffffffffffffffff811115610f3f57610f3f611872565b604051908082528060200260200182016040528015610f7257816020015b6060815260200190600190039081610f5d5790505b50915060005b8151811015610d1b57610f9682828151811061070657610706611843565b838281518110610fa857610fa8611843565b60200260200101819052508080610fbe906118e8565b915050610f78565b80610fd057505050565b602081106110085782518252610fe76020846118d0565b9250610ff46020836118d0565b9150611001602082611921565b9050610fd0565b8015611041576000600161101d836020611921565b61102990610100611aa0565b6110339190611921565b845184518216911916178352505b505050565b80516000901580611058575081516021105b1561108f576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061109e836020015161099b565b905060008184600001516110b29190611921565b90506000808386602001516110c791906118d0565b90508051915060208310156108eb57506020919091036101000a90049392505050565b6110f261132d565b60006110fd8361049d565b90506111158160008151811061063b5761063b611843565b61ffff168252805161113490829060019081106102b1576102b1611843565b826020018190525061115f8160028151811061115257611152611843565b602002602001015161117d565b82604001819052506102be8160038151811061061357610613611843565b61118561135a565b60006111908361049d565b90506111a8816000815181106107a2576107a2611843565b825280516111c3908290600190811061077757610777611843565b82602001819052506111e18160028151811061077757610777611843565b82604001819052506111ff8160038151811061063b5761063b611843565b63ffffffff16606083015250919050565b6040805160c0810190915260006080820181815260a083019190915281526020810161123a611254565b815260200161124761127b565b8152602001606081525090565b60405180606001604052806112676112e1565b815260006020820152606060409091015290565b6040518061010001604052806060815260200160608152602001606081526020016112a4611308565b81526020016112c6604051806040016040528060008152602001600081525090565b81526020016060815260200160608152602001606081525090565b60405180606001604052806112f461132d565b815260200160608152602001606081525090565b604051806040016040528061131b611391565b8152602001611328611391565b905290565b60408051608081018252600081526060602082015290810161134d61135a565b8152600060209091015290565b6040805160c0810190915260006080820181815260a0830191909152815260208101611384611308565b815260200161134d611308565b60405180604001604052806002906020820280368337509192915050565b600080858511156113bf57600080fd5b838611156113cc57600080fd5b5050820193919092039150565b6000815180845260005b818110156113ff576020818501810151868301820152016113e3565b81811115611411576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b6002811015611467578151845260209384019390910190600101611448565b50505050565b611478828251611444565b60208101516110416040840182611444565b600081518084526020808501945080840160005b838110156114c057815163ffffffff168752958201959082019060010161149e565b509495945050505050565b600081518084526020808501945080840160005b838110156114c0576114fc87835180518252602090810151910152565b60409690960195908201906001016114df565b600081518084526020808501808196508360051b8101915082860160005b8581101561155757828403895261154584835161148a565b9885019893509084019060010161152d565b5091979650505050505050565b6000610180825181855261157a8286018261148a565b9150506020830151848203602086015261159482826114cb565b915050604083015184820360408601526115ae82826114cb565b91505060608301516115c3606086018261146d565b506080830151805160e08601526020015161010085015260a08301518482036101208601526115f2828261148a565b91505060c083015184820361014086015261160d828261148a565b91505060e0830151848203610160860152611628828261150f565b95945050505050565b600060208083528351805182850152818101519050604063ffffffff80831682870152838701519250606060a08188015283518160c08901528051826101208a015261ffff8151166101808a0152868101516101c0806101a08c015261169b6103408c01836113d9565b9150868301516116b8828d01825180518252602090810151910152565b8981015191506116cc6102008d018361146d565b8781015191506116e06102808d018361146d565b8501519095166103008b0152908301516103208a0152818701518982037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee09081016101408c01529094509061173581866113d9565b928601518a84039092016101608b015250909250611753838261148a565b9585015163ffffffff811660e08a015295925061176d9050565b8284015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40878303016101008801526117a882866113d9565b94508288015193507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09250828786030160808801526117e78585611564565b94508088015193505050808584030160a08601525061162882826113d9565b60006020828403121561181857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461183c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156118e3576118e36118a1565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561191a5761191a6118a1565b5060010190565b600082821015611933576119336118a1565b500390565b600060ff821660ff841680821015611952576119526118a1565b90039392505050565b600060ff821660ff84168060ff03821115611978576119786118a1565b019392505050565b600181815b808511156119d957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119bf576119bf6118a1565b808516156119cc57918102915b93841c9390800290611985565b509250929050565b6000826119f057506001610bf5565b816119fd57506000610bf5565b8160018114611a135760028114611a1d57611a39565b6001915050610bf5565b60ff841115611a2e57611a2e6118a1565b50506001821b610bf5565b5060208310610133831016604e8410600b8410161715611a5c575081810a610bf5565b611a668383611980565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611a9857611a986118a1565b029392505050565b600061183c83836119e156fea26469706673582212204293d121f63fa7ddf549011f940cab20b905d1148cfb4ca168bb240c5207a01864736f6c634300080c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c80632418833f1461015d5780632b7ac3f314610178578063c4d66de8146101c3575b6004361161007b576040517f0f601ef500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061008a36600481846113af565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394506100cc92508491506101d89050565b6000546040517f1e5de2ab00000000000000000000000000000000000000000000000000000000815291925062010000900473ffffffffffffffffffffffffffffffffffffffff1690631e5de2ab90610129908490600401611631565b60006040518083038186803b15801561014157600080fd5b505afa158015610155573d6000803e3d6000fd5b505050505050005b610165600481565b6040519081526020015b60405180910390f35b60005461019e9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016f565b6101d66101d1366004611806565b6102c9565b005b6101e0611210565b600061021b6102168460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61049d565b90506102408160008151811061023357610233611843565b60200260200101516105dc565b82528051610268908290600190811061025b5761025b611843565b6020026020010151610659565b82602001819052506102938160028151811061028657610286611843565b60200260200101516106db565b82604001819052506102be816003815181106102b1576102b1611843565b6020026020010151610821565b606083015250919050565b600054610100900460ff16158080156102e95750600054600160ff909116105b806103035750303b158015610303575060005460ff166001145b610393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff851602179055801561049957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60606104a8826108f4565b6104de576040517fc0098bd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104e983610918565b90508067ffffffffffffffff81111561050457610504611872565b60405190808252806020026020018201604052801561054957816020015b60408051808201909152600080825260208201528152602001906001900390816105225790505b509150600061055b846020015161099b565b846020015161056a91906118d0565b90506000805b838110156105d35761058183610a21565b91506040518060400160405280838152602001848152508582815181106105aa576105aa611843565b60209081029190910101526105bf82846118d0565b9250806105cb816118e8565b915050610570565b50505050919050565b604080518082019091526000808252602082015260006105fb8361049d565b90506106208160008151811061061357610613611843565b6020026020010151610b32565b82528051610648908290600190811061063b5761063b611843565b6020026020010151610bea565b63ffffffff16602083015250919050565b610661611254565b600061066c8361049d565b90506106918160008151811061068457610684611843565b6020026020010151610bfb565b825280516106ac908290600190811061063b5761063b611843565b63ffffffff16602083015280516106d090829060029081106102b1576102b1611843565b604083015250919050565b6106e361127b565b60006106ee8361049d565b90506107138160008151811061070657610706611843565b6020026020010151610c6c565b8252805161073b908290600190811061072e5761072e611843565b6020026020010151610d22565b82602001819052506107598160028151811061072e5761072e611843565b82604001819052506107848160038151811061077757610777611843565b6020026020010151610de4565b82606001819052506107af816004815181106107a2576107a2611843565b6020026020010151610eb9565b82608001819052506107cd8160058151811061070657610706611843565b8260a001819052506107eb8160068151811061070657610706611843565b8260c001819052506108168160078151811061080957610809611843565b6020026020010151610f16565b60e083015250919050565b805160609061085c576040517fa9bee26000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061086b836020015161099b565b9050600081846000015161087f9190611921565b905060008167ffffffffffffffff81111561089c5761089c611872565b6040519080825280601f01601f1916602001820160405280156108c6576020820181803683370190505b50905060006020820190506108eb8487602001516108e491906118d0565b8285610fc6565b50949350505050565b805160009061090557506000919050565b50602001515160c060009190911a101590565b805160009061092957506000919050565b600080610939846020015161099b565b846020015161094891906118d0565b905060008460000151856020015161096091906118d0565b90505b808210156109925761097482610a21565b61097e90836118d0565b91508261098a816118e8565b935050610963565b50909392505050565b8051600090811a60808110156109b45750600092915050565b60b860ff821610156109c95750600192915050565b60c060ff82161015610a00576109e1600160b8611938565b6109eb9082611938565b6109f690600161195b565b60ff169392505050565b60f860ff82161015610a155750600192915050565b6109e1600160f8611938565b80516000908190811a6080811015610a3c5760019150610b2b565b60b860ff82161015610a6857610a53608082611938565b610a5e90600161195b565b60ff169150610b2b565b60c060ff82161015610ac6576000610a82600160b8611938565b610a8c9083611938565b60ff169050600085600101826020036101000a81510491505080826001610ab391906118d0565b610abd91906118d0565b93505050610b2b565b60f860ff82161015610add57610a5360c082611938565b6000610aeb600160f8611938565b610af59083611938565b60ff169050600085600101826020036101000a81510491505080826001610b1c91906118d0565b610b2691906118d0565b935050505b5092915050565b8051600090610b6d576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b7c836020015161099b565b90506000818460000151610b909190611921565b905080602014610bcc576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080838660200151610bdf91906118d0565b519695505050505050565b6000610bf582611046565b92915050565b610c036112e1565b6000610c0e8361049d565b9050610c3381600081518110610c2657610c26611843565b60200260200101516110ea565b82528051610c4e90829060019081106102b1576102b1611843565b82602001819052506106d08160028151811061070657610706611843565b60606000610c798361049d565b9050805167ffffffffffffffff811115610c9557610c95611872565b604051908082528060200260200182016040528015610cbe578160200160208202803683370190505b50915060005b8151811015610d1b57610ce282828151811061063b5761063b611843565b838281518110610cf457610cf4611843565b63ffffffff9092166020928302919091019091015280610d13816118e8565b915050610cc4565b5050919050565b60606000610d2f8361049d565b9050805167ffffffffffffffff811115610d4b57610d4b611872565b604051908082528060200260200182016040528015610d9057816020015b6040805180820190915260008082526020820152815260200190600190039081610d695790505b50915060005b8151811015610d1b57610db48282815181106107a2576107a2611843565b838281518110610dc657610dc6611843565b60200260200101819052508080610ddc906118e8565b915050610d96565b610dec611308565b6000610df78361049d565b90506000610e1e82600081518110610e1157610e11611843565b602002602001015161049d565b90506000610e3883600181518110610e1157610e11611843565b9050610e508260008151811061063b5761063b611843565b8451528151610e6c908390600190811061063b5761063b611843565b8451602001528051610e8990829060009061063b5761063b611843565b6020850151528051610ea8908290600190811061063b5761063b611843565b602085810151015250919392505050565b60408051808201909152600080825260208201526000610ed88361049d565b9050610ef08160008151811061063b5761063b611843565b82528051610f0b908290600190811061063b5761063b611843565b602083015250919050565b60606000610f238361049d565b9050805167ffffffffffffffff811115610f3f57610f3f611872565b604051908082528060200260200182016040528015610f7257816020015b6060815260200190600190039081610f5d5790505b50915060005b8151811015610d1b57610f9682828151811061070657610706611843565b838281518110610fa857610fa8611843565b60200260200101819052508080610fbe906118e8565b915050610f78565b80610fd057505050565b602081106110085782518252610fe76020846118d0565b9250610ff46020836118d0565b9150611001602082611921565b9050610fd0565b8015611041576000600161101d836020611921565b61102990610100611aa0565b6110339190611921565b845184518216911916178352505b505050565b80516000901580611058575081516021105b1561108f576040517f2d61ef0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061109e836020015161099b565b905060008184600001516110b29190611921565b90506000808386602001516110c791906118d0565b90508051915060208310156108eb57506020919091036101000a90049392505050565b6110f261132d565b60006110fd8361049d565b90506111158160008151811061063b5761063b611843565b61ffff168252805161113490829060019081106102b1576102b1611843565b826020018190525061115f8160028151811061115257611152611843565b602002602001015161117d565b82604001819052506102be8160038151811061061357610613611843565b61118561135a565b60006111908361049d565b90506111a8816000815181106107a2576107a2611843565b825280516111c3908290600190811061077757610777611843565b82602001819052506111e18160028151811061077757610777611843565b82604001819052506111ff8160038151811061063b5761063b611843565b63ffffffff16606083015250919050565b6040805160c0810190915260006080820181815260a083019190915281526020810161123a611254565b815260200161124761127b565b8152602001606081525090565b60405180606001604052806112676112e1565b815260006020820152606060409091015290565b6040518061010001604052806060815260200160608152602001606081526020016112a4611308565b81526020016112c6604051806040016040528060008152602001600081525090565b81526020016060815260200160608152602001606081525090565b60405180606001604052806112f461132d565b815260200160608152602001606081525090565b604051806040016040528061131b611391565b8152602001611328611391565b905290565b60408051608081018252600081526060602082015290810161134d61135a565b8152600060209091015290565b6040805160c0810190915260006080820181815260a0830191909152815260208101611384611308565b815260200161134d611308565b60405180604001604052806002906020820280368337509192915050565b600080858511156113bf57600080fd5b838611156113cc57600080fd5b5050820193919092039150565b6000815180845260005b818110156113ff576020818501810151868301820152016113e3565b81811115611411576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b6002811015611467578151845260209384019390910190600101611448565b50505050565b611478828251611444565b60208101516110416040840182611444565b600081518084526020808501945080840160005b838110156114c057815163ffffffff168752958201959082019060010161149e565b509495945050505050565b600081518084526020808501945080840160005b838110156114c0576114fc87835180518252602090810151910152565b60409690960195908201906001016114df565b600081518084526020808501808196508360051b8101915082860160005b8581101561155757828403895261154584835161148a565b9885019893509084019060010161152d565b5091979650505050505050565b6000610180825181855261157a8286018261148a565b9150506020830151848203602086015261159482826114cb565b915050604083015184820360408601526115ae82826114cb565b91505060608301516115c3606086018261146d565b506080830151805160e08601526020015161010085015260a08301518482036101208601526115f2828261148a565b91505060c083015184820361014086015261160d828261148a565b91505060e0830151848203610160860152611628828261150f565b95945050505050565b600060208083528351805182850152818101519050604063ffffffff80831682870152838701519250606060a08188015283518160c08901528051826101208a015261ffff8151166101808a0152868101516101c0806101a08c015261169b6103408c01836113d9565b9150868301516116b8828d01825180518252602090810151910152565b8981015191506116cc6102008d018361146d565b8781015191506116e06102808d018361146d565b8501519095166103008b0152908301516103208a0152818701518982037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee09081016101408c01529094509061173581866113d9565b928601518a84039092016101608b015250909250611753838261148a565b9585015163ffffffff811660e08a015295925061176d9050565b8284015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40878303016101008801526117a882866113d9565b94508288015193507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09250828786030160808801526117e78585611564565b94508088015193505050808584030160a08601525061162882826113d9565b60006020828403121561181857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461183c57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156118e3576118e36118a1565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561191a5761191a6118a1565b5060010190565b600082821015611933576119336118a1565b500390565b600060ff821660ff841680821015611952576119526118a1565b90039392505050565b600060ff821660ff84168060ff03821115611978576119786118a1565b019392505050565b600181815b808511156119d957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119bf576119bf6118a1565b808516156119cc57918102915b93841c9390800290611985565b509250929050565b6000826119f057506001610bf5565b816119fd57506000610bf5565b8160018114611a135760028114611a1d57611a39565b6001915050610bf5565b60ff841115611a2e57611a2e6118a1565b50506001821b610bf5565b5060208310610133831016604e8410600b8410161715611a5c575081810a610bf5565b611a668383611980565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611a9857611a986118a1565b029392505050565b600061183c83836119e156fea26469706673582212204293d121f63fa7ddf549011f940cab20b905d1148cfb4ca168bb240c5207a01864736f6c634300080c0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.